<?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: Walmyr</title>
    <description>The latest articles on Forem by Walmyr (@walmyrlimaesilv).</description>
    <link>https://forem.com/walmyrlimaesilv</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%2F275482%2Ffa4fc0d4-5629-4ec4-baa4-107278a7b680.png</url>
      <title>Forem: Walmyr</title>
      <link>https://forem.com/walmyrlimaesilv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/walmyrlimaesilv"/>
    <language>en</language>
    <item>
      <title>Building and Testing a Language Detector App</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Tue, 04 Mar 2025 01:51:56 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/building-and-testing-a-language-detector-app-4m90</link>
      <guid>https://forem.com/walmyrlimaesilv/building-and-testing-a-language-detector-app-4m90</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today's globalized world, it is essential for web applications to cater to users from different linguistic backgrounds. In this blog post, we will explore a simple language detector app that displays a message based on the user's browser language settings. Additionally, we will walk through the process of testing this app using Cypress, a powerful end-to-end testing framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Language Detector App
&lt;/h2&gt;

&lt;p&gt;The language detector app is a basic HTML and JavaScript application that detects the browser's language settings and displays a corresponding message. Below is the content of the &lt;code&gt;index.html&lt;/code&gt; file, which forms the core of the app:&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Language Detector&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&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;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="c1"&gt;// Define translations&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;translations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello! Your browser is set to English.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;es&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;¡Hola! Tu navegador está configurado en Español.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bonjour! Votre navigateur est défini sur Français.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Olá! Seu navegador está definido para Português.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="c1"&gt;// Detect browser language&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userLang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;langCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userLang&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Get base language code (e.g., 'en' from 'en-US')&lt;/span&gt;

      &lt;span class="c1"&gt;// Set message&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;translations&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;langCode&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello! Your browser's language is not listed.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Translations&lt;/strong&gt;: The app defines a set of translations for different languages (&lt;code&gt;en&lt;/code&gt;, &lt;code&gt;es&lt;/code&gt;, &lt;code&gt;fr&lt;/code&gt;, &lt;code&gt;pt&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language Detection&lt;/strong&gt;: It detects the browser's language using &lt;code&gt;navigator.language&lt;/code&gt; or &lt;code&gt;navigator.languages[0]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Display&lt;/strong&gt;: Based on the detected language, it displays the corresponding message from the translations object. If the language is not listed, it displays a default message.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Testing the Language Detector App with Cypress
&lt;/h2&gt;

&lt;p&gt;Cypress is an end-to-end testing framework that makes it easy to write, execute, and debug tests for web applications. In this section, we will create tests to verify that the language detector app displays the correct message based on different browser language settings.&lt;/p&gt;

&lt;p&gt;Below is the content of the &lt;code&gt;cypress/e2e/spec.cy.js&lt;/code&gt; file, which contains the Cypress tests:&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="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Lang App&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="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="s2"&gt;renders with the default language (en-GB)&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello! Your browser is set to English.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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="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="s2"&gt;renders in en-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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&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="nf"&gt;onBeforeLoad &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;language&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-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="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello! Your browser is set to English.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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="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="s2"&gt;renders in es-ES&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&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="nf"&gt;onBeforeLoad &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;language&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;es-ES&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="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;¡Hola! Tu navegador está configurado en Español.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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="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="s2"&gt;renders in fr-FR&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&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="nf"&gt;onBeforeLoad &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;language&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fr-FR&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="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bonjour! Votre navigateur est défini sur Français.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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="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="s2"&gt;renders in pt-BR&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&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="nf"&gt;onBeforeLoad &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;language&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pt-BR&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="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Olá! Seu navegador está definido para Português.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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="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="s2"&gt;renders with a not listed language (nb-NO)&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&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="nf"&gt;onBeforeLoad &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;language&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nb-NO&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="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello! Your browser's language is not listed.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How the Tests Work
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Default Language Test&lt;/strong&gt;: The first test verifies that the app displays the correct message for the default language setting (English).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specific Language Tests&lt;/strong&gt;: The subsequent tests override the browser's language setting (&lt;code&gt;navigator.language&lt;/code&gt;) to simulate different languages (&lt;code&gt;en-US&lt;/code&gt;, &lt;code&gt;es-ES&lt;/code&gt;, &lt;code&gt;fr-FR&lt;/code&gt;, &lt;code&gt;pt-BR&lt;/code&gt;) and verify that the app displays the correct message for each language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not Listed Language Test&lt;/strong&gt;: The final test simulates a browser language setting that is not listed in the translations object (&lt;code&gt;nb-NO&lt;/code&gt;) and verifies that the app displays the default message for unlisted languages.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Running the Tests
&lt;/h3&gt;

&lt;p&gt;To run the Cypress tests, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Cypress&lt;/strong&gt;: Ensure you have Cypress installed in your project. If not, you can install it using npm:
&lt;/li&gt;
&lt;/ol&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;cypress &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open Cypress&lt;/strong&gt;: Open the Cypress test runner:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npx cypress open
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run the Tests&lt;/strong&gt;: In the Cypress test runner, click on the &lt;code&gt;spec.cy.js&lt;/code&gt; file to run the tests.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below the result of the tests executed in headless mode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Lang App
    ✓ renders with the default language &lt;span class="o"&gt;(&lt;/span&gt;en-GB&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;42ms&lt;span class="o"&gt;)&lt;/span&gt;
    ✓ renders &lt;span class="k"&gt;in &lt;/span&gt;en-US &lt;span class="o"&gt;(&lt;/span&gt;21ms&lt;span class="o"&gt;)&lt;/span&gt;
    ✓ renders &lt;span class="k"&gt;in &lt;/span&gt;es-ES &lt;span class="o"&gt;(&lt;/span&gt;16ms&lt;span class="o"&gt;)&lt;/span&gt;
    ✓ renders &lt;span class="k"&gt;in &lt;/span&gt;fr-FR &lt;span class="o"&gt;(&lt;/span&gt;16ms&lt;span class="o"&gt;)&lt;/span&gt;
    ✓ renders &lt;span class="k"&gt;in &lt;/span&gt;pt-BR &lt;span class="o"&gt;(&lt;/span&gt;17ms&lt;span class="o"&gt;)&lt;/span&gt;
    ✓ renders with a not listed language &lt;span class="o"&gt;(&lt;/span&gt;nb-NO&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;20ms&lt;span class="o"&gt;)&lt;/span&gt;


  6 passing &lt;span class="o"&gt;(&lt;/span&gt;166ms&lt;span class="o"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



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

&lt;p&gt;In this blog post, we explored a simple language detector app that displays a message based on the user's browser language settings. We also demonstrated how to write and run end-to-end tests for this app using Cypress. By following these steps, you can ensure that your app behaves correctly for users with different language settings.&lt;/p&gt;

&lt;p&gt;Happy testing!&lt;/p&gt;




&lt;p&gt;The whole code demonstrated in this blog post can be found at &lt;a href="https://github.com/wlsf82/lang-app" rel="noopener noreferrer"&gt;https://github.com/wlsf82/lang-app&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Would you like to learn Cypress in a hands-on course?&lt;/p&gt;

&lt;p&gt;I introduce you to my course: &lt;a href="https://www.udemy.com/course/cypress-from-zero-to-the-cloud/?referralCode=CABCDDFA5ADBB7BE2E1A" rel="noopener noreferrer"&gt;🌲 Cypress, from Zero to the Cloud ☁️&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope you like it!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Radical Simplicity</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Wed, 30 Oct 2024 22:54:37 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/radical-simplicity-360b</link>
      <guid>https://forem.com/walmyrlimaesilv/radical-simplicity-360b</guid>
      <description>&lt;p&gt;Radical simplicity in software design and development refers to the principle of creating systems, architectures, and user experiences that prioritize minimalism, clarity, and ease of use. The goal is to strip away unnecessary complexity and focus on the core functionality and essential features that deliver the most value to users. This concept advocates for simplifying code, design choices, and workflows to the point where the system is intuitive, easy to maintain, and efficient, both in performance and usability.&lt;/p&gt;

&lt;p&gt;Key aspects of radical simplicity include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Focus on Essential Features&lt;/strong&gt;: Developers avoid feature bloat by concentrating only on what truly matters to the user or business goals. Every additional feature or element is carefully scrutinized for its necessity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimization of Complexity&lt;/strong&gt;: The architecture, code, and design choices are streamlined. Complex interdependencies and over-engineered solutions are avoided, ensuring that systems are modular, decoupled, and easy to reason about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Simple designs often lead to cleaner codebases that are easier to maintain, extend, and debug. It enables new team members to onboard quickly and reduces the technical debt over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-Centered Design&lt;/strong&gt;: In the front-end and UX design, radical simplicity means creating interfaces that are easy to navigate and understand, reducing cognitive load for the user. The user experience should feel natural and require minimal instructions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iterative Improvement&lt;/strong&gt;: Radical simplicity is often achieved through continuous iteration, where unnecessary complexity is stripped away in each cycle, with the aim of achieving an elegant, focused solution.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By embracing radical simplicity, teams can create systems that are not only highly functional but also resilient, adaptable, and scalable over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Radical simplicity in the context of Cypress web test automation
&lt;/h2&gt;

&lt;p&gt;In the context of web test automation, radical simplicity involves creating tests and testing strategies that are easy to implement, maintain, and scale. When using &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; as a testing framework, applying the concept of radical simplicity can result in more efficient, reliable, and maintainable test suites. Here’s how this principle manifests in Cypress-based test automation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Minimalistic Test Design&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Radical simplicity in Cypress test design encourages writing concise, focused tests that target core functionality. Rather than bloating tests with unnecessary steps or covering too many aspects in a single test, Cypress allows you to break tests into smaller, more manageable pieces. Each test should focus on a specific part of the application, reducing complexity and making tests easier to understand and debug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Instead of a single, long test that checks multiple features of a page, split it into smaller tests, each checking one feature. This improves readability and helps isolate failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Declarative Testing with Cypress&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cypress’s syntax and API are inherently simple and declarative. Its commands mirror the way users interact with web applications, making tests more intuitive. This aligns well with the principle of radical simplicity, as tests are often straightforward to write and read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Cypress provides commands like &lt;a href="https://on.cypress.io/get" rel="noopener noreferrer"&gt;&lt;code&gt;cy.get()&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://on.cypress.io/click" rel="noopener noreferrer"&gt;&lt;code&gt;.click()&lt;/code&gt;&lt;/a&gt; that map directly to user actions, allowing tests to be written in a way that closely mirrors the user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Reducing Setup Complexity with Auto-Retries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cypress automatically retries assertions and commands until they pass or fail, which eliminates the need for adding explicit waits or complex timing logic to your tests. This simplifies the overall structure of tests by reducing the need for handling asynchronous code, allowing tests to focus on core functionality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Instead of adding &lt;code&gt;cy.wait(1000)&lt;/code&gt; to ensure an element appears, Cypress will automatically retry a &lt;code&gt;cy.get()&lt;/code&gt; command until the element is available or a timeout is reached. This keeps the code clean and simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Simplified End-to-End (E2E) Testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cypress simplifies E2E testing by running directly in the browser and having access to real-time feedback from the application under test. This eliminates the complexity of setting up separate drivers or configuring external tools for browser automation (as with Selenium), leading to simpler, more straightforward E2E tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: With Cypress, there is no need to install additional browser drivers or run separate services for executing tests. Everything runs locally in the same environment, reducing setup and potential points of failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Maintainable Test Suites through Best Practices&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cypress encourages the use of maintainable patterns like fixtures, and custom commands, which adhere to the principle of radical simplicity by keeping test code modular, reusable, and easy to update.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Using fixtures for test data reduces duplication and centralizes the management of test data, making it easier to update when changes occur. Similarly, custom commands allow the encapsulation of repetitive sequences of commands, improving code readability and reducing redundancy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. &lt;code&gt;cy.intercept&lt;/code&gt; for API interception&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://on.cypress.io/intercept" rel="noopener noreferrer"&gt;&lt;code&gt;cy.intercept()&lt;/code&gt;&lt;/a&gt; command simplifies GUI testing and network stubbing in Cypress, allowing for the interception and manipulation of network requests without adding external mocking libraries or complex setup. This keeps test logic clear and focused on testing application behavior, rather than managing network dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Instead of setting up a mock server or waiting for real API responses, &lt;code&gt;cy.intercept()&lt;/code&gt; allows you to simulate different responses directly in the test, making GUI testing both simpler and faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Error Handling and Debugging&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cypress provides automatic screenshots and videos on test failures, besides the &lt;a href="https://docs.cypress.io/cloud/features/test-replay" rel="noopener noreferrer"&gt;Test Replay&lt;/a&gt; feature, which radically simplifies debugging. Developers don’t need to add extra logging or error-handling code in the tests to troubleshoot. This helps keep the tests simple while still being able to efficiently diagnose issues when they occur.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: When a test fails, Cypress provides a snapshot of the application state at the point of failure. This eliminates the need for extra boilerplate code to capture logs or states during test execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Integrated Assertions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cypress has built-in assertions, such as checking for visibility, text content, and attributes, which simplifies the testing process. Instead of using external assertion libraries or verbose assertions, Cypress integrates these directly into its chainable commands, keeping the test code minimal and easier to read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Assertions like &lt;code&gt;cy.contains('button', 'Submit').should('be.visible')&lt;/code&gt; are built into the Cypress command chain, allowing for a more streamlined syntax without the need for external libraries or excessive boilerplate code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Simplified CI/CD Integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cypress is designed to integrate seamlessly with CI/CD pipelines. Its architecture, combined with simple configurations for parallel testing, reporting, and failure handling, reduces the complexity typically associated with setting up test automation in continuous integration environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Cypress provides easy integration with services like GitHub Actions, CircleCI, and others, ensuring that tests can be run consistently and reliably without having to manually configure browsers, dependencies, or parallel execution strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;By leveraging Cypress’s design and capabilities, you can achieve radical simplicity in web test automation. The framework’s emphasis on minimal setup, intuitive commands, and modular test patterns aligns with the core idea of focusing on what’s essential, eliminating unnecessary complexity, and creating a sustainable and maintainable test suite. This allows teams to focus on delivering high-quality software without being bogged down by the intricacies of a complex testing setup.&lt;/p&gt;




&lt;p&gt;Radical simplicity is a guiding principle that transcends specific tools, extending to how we approach software design, development, and testing as a whole. Embracing radical simplicity means creating systems that prioritize clarity, functionality, and ease of use while reducing unnecessary complexity. By focusing on essential features, minimizing architectural and code complexity, and centering on user experience, teams can build software that is not only resilient and scalable but also intuitive and accessible to users. Whether applied to development, testing, or user interface design, radical simplicity fosters maintainability, adaptability, and efficiency, helping teams create lasting, high-impact solutions that align with both immediate needs and long-term goals.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Test Design: What Everyone Should Know About Test Automation</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Sun, 13 Oct 2024 01:25:54 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/test-design-what-everyone-should-know-about-test-automation-b68</link>
      <guid>https://forem.com/walmyrlimaesilv/test-design-what-everyone-should-know-about-test-automation-b68</guid>
      <description>&lt;h2&gt;
  
  
  How solid test design turns automation into a trustworthy quality signal
&lt;/h2&gt;

&lt;p&gt;In the world of test automation, success isn't just about writing tests that pass or fail—it's about crafting solutions that are fast, reliable, maintainable, and scalable. Effective test automation is built on fundamental principles that ensure tests aren't just solving the problems of today but are also ready to tackle the challenges of tomorrow. Here, we’ll dive into what I call &lt;em&gt;The Elements of Test Design&lt;/em&gt;—15 key principles that, when applied, will help you design efficient and future-proof test automation systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Suite, Sub-suite, and Test Cases’ Descriptions
&lt;/h3&gt;

&lt;p&gt;Clarity in your test suite hierarchy and descriptions is foundational. Every suite, sub-suite, and test case should have a purpose that is clear at a glance. Descriptive and meaningful names help teams quickly understand what’s being tested and why. Think of this as your first layer of communication—tests should tell a story about the system’s behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Test Levels
&lt;/h3&gt;

&lt;p&gt;Different types of tests serve different purposes. Unit tests, integration tests, end-to-end tests, and performance tests each focus on specific layers of the application. Effective test automation design requires a strategic approach to layering these test levels. Too much focus on end-to-end tests can lead to slow, fragile test suites, while too much emphasis on unit tests can miss critical system-wide behaviors. The goal is to strike a balance that maximizes coverage while maintaining test suite stability and speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Abstractions
&lt;/h3&gt;

&lt;p&gt;Abstractions are crucial to prevent repetitive code and reduce maintenance costs. Instead of repeating the same logic in multiple places, modularize common functionality and group related behaviors into reusable modules. This principle simplifies test design, enhances reusability, and allows you to focus on what’s truly important: the behavior under test. Modules help keep the test code DRY (Don’t Repeat Yourself) while allowing you to manage complexity in a clean, structured way.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Assertions
&lt;/h3&gt;

&lt;p&gt;Assertions verify that the expected outcome matches the actual result. A strong test should have precise assertions that validate the critical behavior of your system. Avoid testing too many things at once, as it can lead to unclear failure points. Each test should focus on verifying a specific aspect of the application to make failures more diagnosable.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Independence
&lt;/h3&gt;

&lt;p&gt;Tests should be independent, meaning the outcome of one test should not depend on the result or state of another. This principle is often overlooked, leading to fragile test suites that break when the order of execution changes. Independence ensures that each test can be run in isolation, which makes parallel execution possible, speeding up the test suite significantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Infrastructure and Environments
&lt;/h3&gt;

&lt;p&gt;The test environment should closely mimic production to catch real-world issues. Managing infrastructure is a complex but necessary aspect of test automation. With tools like Docker or cloud-based services, it's possible to create scalable, disposable environments for testing. By using infrastructure-as-code and environment automation, you can ensure consistency and reduce “it works on my machine” issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Tools
&lt;/h3&gt;

&lt;p&gt;Choosing the right tools for the job is vital. From test runners to assertion libraries and CI/CD tools, the test automation ecosystem offers numerous options. Pick tools that integrate well with your stack, support your goals (speed, maintainability, etc.), and align with the skill set of your team. But remember, tools are just enablers—the core of good test design remains the underlying principles.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Accessibility
&lt;/h3&gt;

&lt;p&gt;Testing accessibility is often an afterthought but shouldn’t be. As more teams adopt accessibility-first approaches, ensuring your test automation framework can handle accessibility tests (such as checking for screen reader support or color contrast) is becoming increasingly important. Automated accessibility testing helps catch usability issues that may be missed during manual testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Testability
&lt;/h3&gt;

&lt;p&gt;Good design considers how testable the application is. If it's difficult to test, it’s a sign that the code itself may need refactoring. By improving the testability of the system, such as using dependency injection or exposing APIs specifically for testing, you can make your application easier to validate and more robust.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Security
&lt;/h3&gt;

&lt;p&gt;Security tests ensure that your application is not only functional but also safe from potential vulnerabilities. Automation can cover common security concerns like SQL injection, XSS attacks, or unauthorized access. One critical aspect is ensuring that sensitive data, such as passwords or API keys, is never versioned or exposed in your code repository. Make sure to use secure variables in your CI/CD pipeline and tools, and automate the scanning of your codebase for known vulnerabilities. Additionally, it's essential to incorporate automatic patching mechanisms that can address security vulnerabilities as they arise.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. Tests' Size
&lt;/h3&gt;

&lt;p&gt;The size of tests matters. Larger tests tend to be slower and more brittle, especially if they cover too much ground. A key principle in test design is to keep tests as small as possible while still validating the desired behavior. This helps to reduce the noise in failure reports and ensures faster execution, which is critical for maintaining a fast feedback loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  12. Conventions
&lt;/h3&gt;

&lt;p&gt;Adopting conventions in your test design leads to consistency across the test suite. Whether it’s naming conventions, file structures, or coding style, following agreed-upon patterns makes the test suite easier to navigate and maintain, particularly when scaling the test coverage over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  13. The 3A Pattern (Arrange, Act, Assert)
&lt;/h3&gt;

&lt;p&gt;The AAA pattern—Arrange, Act, Assert—provides a clean and simple way to structure your tests. By clearly separating the setup (Arrange), the action being tested (Act), and the validation (Assert), you ensure that tests are readable and organized. This structure makes it easier to see what’s being tested and why, while helping to avoid test logic creeping into setup or validation phases.&lt;/p&gt;

&lt;h3&gt;
  
  
  14. Performance Optimizations
&lt;/h3&gt;

&lt;p&gt;Performance matters in test automation. Over time, as test suites grow, execution times tend to increase. To combat this, it’s crucial to regularly optimize tests for speed. Consider parallel execution, optimizing setup, and eliminating unnecessary waits or redundancies. Performance optimizations can also involve revisiting test levels and ensuring that only critical scenarios are covered in the more expensive end-to-end tests, while unit tests handle most validations.&lt;/p&gt;

&lt;h3&gt;
  
  
  15. Test Stability and Reliability
&lt;/h3&gt;

&lt;p&gt;A test suite is only valuable if teams can trust its results. Tests must be stable, deterministic, and resilient to non-functional changes such as timing fluctuations, data noise, or environmental variations. Flaky tests—those that fail intermittently without real defects—erode confidence and are quickly ignored or disabled, undermining the entire automation effort. Designing for stability means minimizing dependencies on unstable elements, avoiding unnecessary waits, controlling test data, and favoring deterministic assertions. Equally important, stable tests should require minimal maintenance as the system evolves, changing only when behavior truly changes. The ultimate goal is to provide fast, reliable feedback that teams can confidently depend on to make decisions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Solving Complex Test Automation Challenges with Simplicity
&lt;/h2&gt;

&lt;p&gt;By applying &lt;em&gt;The Elements of Test Design&lt;/em&gt;, you can address complex test automation challenges with simple yet effective strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Balance Test Levels:&lt;/strong&gt; Don’t overload your test suite with slow and fragile end-to-end tests. By leveraging unit and integration tests for most validations and reserving end-to-end tests for critical paths, you reduce flakiness while maintaining both speed and coverage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Abstract Intelligently:&lt;/strong&gt; Use abstractions to reduce duplication, but don’t over-engineer. Simple, behavior-focused abstractions not only improve maintainability but also contribute to test stability by centralizing changes and reducing inconsistent implementations across tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimize for Speed and Stability:&lt;/strong&gt; Fast tests are important, but fast and flaky tests are useless. Continuously evaluate your test suite for performance bottlenecks and sources of instability, such as unnecessary waits, race conditions, or environment-dependent behavior. Speed should amplify reliability, not compromise it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Design for Reliability:&lt;/strong&gt; Treat flaky tests as production bugs. Invest in deterministic test data, controlled environments, and clear assertions that fail only when behavior truly breaks. A reliable test suite builds trust and ensures failures are meaningful and actionable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ensure Independence:&lt;/strong&gt; Test failures should always reflect real issues, not hidden dependencies or leaked state. Independence improves parallelization, simplifies debugging, and is a key factor in achieving long-term test stability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use the Right Tools:&lt;/strong&gt; Let the problem drive the tool selection. Favor tools and frameworks that promote determinism, good diagnostics, and easy isolation of tests. A tool that makes tests easy to write but hard to stabilize will slow teams down in the long run.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By embracing these principles, you’ll create a test automation suite that is not only robust, scalable, and maintainable, but also trusted. Stability and reliability transform automation from a safety net into a decision-making engine, giving teams the confidence to move fast without sacrificing quality.&lt;/p&gt;




&lt;p&gt;This holistic approach to test design turns your automation efforts into a strategic advantage, ensuring you aren’t just testing for today but building a system that can adapt and grow with the complexity of your application over time.&lt;/p&gt;




&lt;p&gt;Hi, my name is &lt;a href="https://walmyr.dev" rel="noopener noreferrer"&gt;Walmyr&lt;/a&gt;, and I teach about test design to software professionals.&lt;/p&gt;

&lt;p&gt;If you're interested in Test Design Training, reach out to me on &lt;a href="https://www.linkedin.com/in/walmyr-lima-e-silva-filho/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and let's talk.&lt;/p&gt;




&lt;p&gt;Happy testing! 👋&lt;/p&gt;




&lt;p&gt;This content was translated to Portuguese, and you can find the &lt;a href="https://talkingabouttesting.com/2024/10/13/design-de-testes-o-que-todo-mundo-deveria-saber-sobre-automacao-de-testes/" rel="noopener noreferrer"&gt;translated version at the Talking About Testing blog&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Logging into different environments with Cypress</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Fri, 26 Jan 2024 06:30:00 +0000</pubDate>
      <link>https://forem.com/cypress/logging-into-different-environments-with-cypress-l6i</link>
      <guid>https://forem.com/cypress/logging-into-different-environments-with-cypress-l6i</guid>
      <description>&lt;h2&gt;
  
  
  Learn how to log into different environments with Cypress, protecting sensitive data, such as username and password
&lt;/h2&gt;

&lt;p&gt;In another blog post of the &lt;strong&gt;Pinches of Cypress&lt;/strong&gt; series, I wrote about &lt;a href="https://dev.to/walmyrlimaesilv/how-to-change-the-baseurl-via-command-line-with-cypress-1olm"&gt;how to change the baseUrl via the command line with Cypress&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But what about sensitive data, such as credentials for authentication in the same application, deployed in different environments? That's precisely what I'll teach you in this content!&lt;/p&gt;

&lt;p&gt;Let's imagine an application deployed in three different environments, each with its specific credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local (your computer)&lt;/li&gt;
&lt;li&gt;Staging&lt;/li&gt;
&lt;li&gt;Production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The user's email and password are required to log into the application (in any of the environments).&lt;/p&gt;

&lt;p&gt;Let's also assume that in the Cypress configuration file (&lt;code&gt;cypress.json&lt;/code&gt;, or &lt;code&gt;cypress.config.js&lt;/code&gt; – from version 10 onwards), the &lt;code&gt;baseUrl&lt;/code&gt; points by default to the local development environment, as shown below:&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;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000"&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;Above is the configuration file before Cypress version 10.&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;// cypress/config/cypress.config.js (from version 10 onwards)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cypress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;e2e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above is the configuration file from Cypress version 10 onwards.&lt;/p&gt;

&lt;p&gt;However, the staging and production environments have the following URLs, respectively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://example.staging.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://example.com&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's also assume that in the &lt;code&gt;package.json&lt;/code&gt; file, we have the following scripts for running tests in each specific environment:&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="nl"&gt;"scripts"&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;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cypress run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test:staging"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cypress run --config baseUrl=https://example.staging.com --env environment=staging"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test:prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cypress run --config baseUrl=https://example.com --env environment=prod"&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 &lt;code&gt;test&lt;/code&gt; script executes the tests against the local environment since the &lt;code&gt;baseUrl&lt;/code&gt; is not overridden.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;test:staging&lt;/code&gt; and &lt;code&gt;test:prod&lt;/code&gt; scripts, the &lt;code&gt;baseUrl&lt;/code&gt; is overridden via the command line. Additionally, we pass a variable called &lt;code&gt;environment&lt;/code&gt; with a value that identifies each environment (&lt;code&gt;staging&lt;/code&gt; and &lt;code&gt;prod&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In the local environment, we can have an unversioned file (included in the &lt;code&gt;.gitignore&lt;/code&gt; file) called &lt;code&gt;cypress.env.json&lt;/code&gt;, which would have the following structure:&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;"LOCAL_USER"&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;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"local@user.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the-password-of-the-above-user"&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;"STAGING_USER"&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;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"some-user@example.staging.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the-password-of-the-above-user"&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;"PROD_USER"&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;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"another-user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the-password-of-the-above-user"&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;&lt;strong&gt;Note:&lt;/strong&gt; I also recommend creating a versioned file called &lt;code&gt;cypress.env.example.json&lt;/code&gt; with example values so other team members can use it as a template for creating their own unversioned &lt;code&gt;cypress.env.json&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note 2:&lt;/strong&gt; In a continuous integration environment, such values (&lt;code&gt;STAGING_USER&lt;/code&gt; and &lt;code&gt;PROD_USER&lt;/code&gt;) could be set as secrets, with the prefix &lt;code&gt;CYPRESS_&lt;/code&gt;, i.e., &lt;code&gt;CYPRESS_STAGING_USER&lt;/code&gt; and &lt;code&gt;CYPRESS_PROD_USER&lt;/code&gt;, with their respective values.&lt;/p&gt;

&lt;p&gt;Now that we have the credentials let's implement a custom command for logging in based on the environment where the tests are being executed.&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;// cypress/support/commands.js&lt;/span&gt;

&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;login&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Logging into the &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;environment&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;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;environment&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;local&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; environment`&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;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;staging&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;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;STAGING_USER&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;else&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;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod&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;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PROD_USER&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LOCAL_USER&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="emailField"]&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="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="passwordField"]&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="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Login&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="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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="nf"&gt;click&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 the login custom command, we dynamically set the &lt;code&gt;user&lt;/code&gt; variable depending on the environment passed via the command line in the npm script. Thus, we can use this variable in commands that enter the user's email and password.&lt;/p&gt;

&lt;p&gt;Additionally, we log the phrase &lt;em&gt;"Logging into the [environment] environment"&lt;/em&gt; in the Cypress command log, depending on the environment where the tests are running. If the &lt;code&gt;environment&lt;/code&gt; variable is passed, we use it; otherwise, the default is the &lt;code&gt;local&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;So, if the value of the &lt;code&gt;environment&lt;/code&gt; variable is, for example, &lt;code&gt;staging&lt;/code&gt;, the following would be "printed" in the Cypress command log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Logging into the staging environment.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the login test would look something like this:&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;// cypress/integration/login.spec.js (before Cypress version 10)&lt;/span&gt;
&lt;span class="c1"&gt;// or cypress/e2e/login.cy.js (from Cypress version 10 onwards)&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;logs in&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="avatar"]&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="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, in the actual test, we only call the custom command &lt;code&gt;cy.login&lt;/code&gt;, which authenticates the application with the correct credentials.&lt;/p&gt;

&lt;p&gt;That's it! I hope you learned something new.&lt;/p&gt;




&lt;p&gt;For more details on how Cypress works, I recommend reading the &lt;a href="https://docs.cypress.io/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Did you like the content? Leave a comment.&lt;/p&gt;




&lt;p&gt;This blog post was originally published in Portuguese at the &lt;a href="https://talkingabouttesting.com/2021/10/09/como-fazer-login-com-cypress-em-diferentes-ambientes/" rel="noopener noreferrer"&gt;Talking About Testing&lt;/a&gt; blog.&lt;/p&gt;




&lt;p&gt;Would you like to learn Cypress in a hands-on course?&lt;/p&gt;

&lt;p&gt;I introduce you to my newest course, &lt;a href="https://www.udemy.com/course/cypress-from-zero-to-the-cloud/?referralCode=CABCDDFA5ADBB7BE2E1A" rel="noopener noreferrer"&gt;🌲 Cypress, from Zero to the Cloud ☁️&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope you like it, and happy testing!&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>testing</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Simulating Internet Outage and Recovery using Cypress</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Fri, 26 Jan 2024 00:57:52 +0000</pubDate>
      <link>https://forem.com/cypress/simulating-internet-outage-and-recovery-using-cypress-5hjk</link>
      <guid>https://forem.com/cypress/simulating-internet-outage-and-recovery-using-cypress-5hjk</guid>
      <description>&lt;h2&gt;
  
  
  Unveiling Cypress's Power: Testing Internet Outages and Recoveries with Precision
&lt;/h2&gt;

&lt;p&gt;Testing an application under various scenarios is crucial to ensure its robustness and user-friendliness.&lt;/p&gt;

&lt;p&gt;One common yet challenging scenario is simulating internet outages and recoveries.&lt;/p&gt;

&lt;p&gt;In this blog post, we'll explore a &lt;a href="https://cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; test that replicates this scenario, utilizing the powerful &lt;a href="https://on.cypress.io/intercept" rel="noopener noreferrer"&gt;&lt;code&gt;intercept&lt;/code&gt;&lt;/a&gt; command to manipulate network requests and responses.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This blog post was originated by the following &lt;a href="https://github.com/wlsf82/cypress-playground/blob/main/cypress/e2e/playground.cy.js#L149C3-L175C5" rel="noopener noreferrer"&gt;test&lt;/a&gt;, from the &lt;a href="https://github.com/wlsf82/cypress-playground" rel="noopener noreferrer"&gt;Cypress Playground&lt;/a&gt; repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Test Scenario
&lt;/h3&gt;

&lt;p&gt;The test aims to simulate the internet going "down" and then recovering.&lt;/p&gt;

&lt;p&gt;Let's walk through the code step by step to understand how it achieves this:&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;// Complete Code&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;simulates the internet going "down" then back "up"&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="c1"&gt;// Simulating Network Error&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;forceNetworkError&lt;/span&gt;&lt;span class="p"&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;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;networkError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Triggering the Request&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Get TODO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// Handling the Network Error&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@networkError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.error span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oops, something went wrong. Check your internet connection, refresh the page, and try again.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Triggering Recovery&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// Simulating Successful Request&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;middleware&lt;/span&gt;&lt;span class="p"&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;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getTodo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Get TODO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@getTodo&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="nf"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;response.statusCode&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="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.equal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Validating Result&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TODO ID: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Completed: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User ID: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breaking It Down
&lt;/h3&gt;

&lt;p&gt;Let's break it down, so you can understand each piece of code step-by-step.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Simulating Network Error
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;forceNetworkError&lt;/span&gt;&lt;span class="p"&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;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;networkError&lt;/span&gt;&lt;span class="dl"&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 section, we use the &lt;code&gt;cy.intercept&lt;/code&gt; command to intercept any GET request to the specified URL (&lt;code&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/code&gt;). The interception is configured to force a network error (&lt;code&gt;forceNetworkError: true&lt;/code&gt;). The interception is named 'networkError' using the &lt;code&gt;as&lt;/code&gt; command, allowing us to wait for it later.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Triggering the Request
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Get TODO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line simulates a user action by clicking a button with the text 'Get TODO.' This triggers the intercepted GET request, and Cypress will capture the interception labeled as 'networkError.'&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Handling the Network Error
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@networkError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;cy.wait('@networkError')&lt;/code&gt; command pauses the test execution until the intercepted request labeled 'networkError' is completed. This ensures that the test waits for the network error response before proceeding.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.error span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oops, something went wrong. Check your internet connection, refresh the page, and try again.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the network error, the test expects to find a visible element with the specified error message. This asserts that the application responds appropriately to a network error, providing a user-friendly message.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Triggering Recovery
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line reloads the page, simulating a user's attempt to recover from the network error.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Simulating Successful Request
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;middleware&lt;/span&gt;&lt;span class="p"&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;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getTodo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we intercept the same GET request, but this time, we simulate a successful response (&lt;code&gt;{ middleware: true }&lt;/code&gt;). The interception is named 'getTodo'.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For more details about the &lt;code&gt;middleware&lt;/code&gt; property, I recommend reading about the &lt;a href="https://docs.cypress.io/api/commands/intercept#Interception-lifecycle" rel="noopener noreferrer"&gt;interception lifecycle&lt;/a&gt;, directly from the Cypress official docs.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Get TODO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another user action triggers the successful request interception.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@getTodo&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="nf"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;response.statusCode&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="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.equal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test waits for the 'getTodo' interception and asserts that the response status code is 200, confirming the successful recovery.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. Validating Result
&lt;/h4&gt;

&lt;p&gt;The subsequent lines validate the presence of specific elements on the page, ensuring that the application displays the expected data after the recovery.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TODO ID: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Completed: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User ID: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These assertions check for the visibility of elements indicating that the application has successfully fetched and displayed the TODO details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This Cypress test provides a comprehensive simulation of internet outage and recovery, allowing testers and developers to evaluate how an application responds to network errors.&lt;/p&gt;

&lt;p&gt;Realistic scenarios, powered by Cypress commands like &lt;code&gt;intercept&lt;/code&gt;, enable effective validation of application behavior under challenging conditions.&lt;/p&gt;

&lt;p&gt;Finally, ensuring meaningful feedback and maintaining robustness are critical aspects of delivering a seamless user experience, even in the face of potential network issues.&lt;/p&gt;




&lt;p&gt;Did you like the content? Leave a comment.&lt;/p&gt;




&lt;p&gt;Would you like to learn Cypress in a hands-on course?&lt;/p&gt;

&lt;p&gt;I introduce you to my newest course, &lt;a href="https://www.udemy.com/course/cypress-from-zero-to-the-cloud/?referralCode=CABCDDFA5ADBB7BE2E1A" rel="noopener noreferrer"&gt;🌲 Cypress, from Zero to the Cloud ☁️&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope you like it, and happy testing!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>cypress</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Filtering the available browsers in Cypress</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Thu, 03 Aug 2023 08:34:09 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/filtering-the-available-browsers-in-cypress-1835</link>
      <guid>https://forem.com/walmyrlimaesilv/filtering-the-available-browsers-in-cypress-1835</guid>
      <description>&lt;h2&gt;
  
  
  Learn how to define which browsers will be available to run tests with Cypress
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://cypress.io" rel="noopener noreferrer"&gt;&lt;strong&gt;Cypress&lt;/strong&gt;&lt;/a&gt; is a web test automation framework that comes with everything you need to create automated tests without wasting time with configurations and other details.&lt;/p&gt;

&lt;p&gt;Among its facilities, Cypress identifies which browsers are available on your computer, and when opened, you can select which browser you want to run the tests in, as shown in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fhxchyd8wyjg4ir1t5q9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fhxchyd8wyjg4ir1t5q9k.png" alt="Image description" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, in addition to Chrome, Edge and Firefox browsers (available on my computer when I took this screenshot), there is also the Electron browser, which is the desktop version of Chrome.&lt;/p&gt;

&lt;p&gt;You can also choose in which browser the tests will run in when running them in headless mode (the mode normally used in continuous integration).&lt;/p&gt;

&lt;p&gt;To do so, just run &lt;code&gt;cypress run --browser chrome&lt;/code&gt;, &lt;code&gt;cypress run --browser edge&lt;/code&gt;, or &lt;code&gt;cypress run --browser firefox&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; When running just &lt;code&gt;cypress run&lt;/code&gt;, Cypress will run the tests by default in the Electron browser (the desktop version of Chrome).&lt;/p&gt;

&lt;h3&gt;
  
  
  Making only web browsers available to Cypress
&lt;/h3&gt;

&lt;p&gt;Usually, web applications are used by their users in web browsers, rather than a desktop version of the browser, such as Electron.&lt;/p&gt;

&lt;p&gt;Therefore, in order not to run the risk of running the tests in such a browser, we can remove it from the list of available browsers.&lt;/p&gt;

&lt;p&gt;To do so, simply add the following implementation to the &lt;code&gt;setupNodeEvents&lt;/code&gt; function defined in the &lt;code&gt;e2e&lt;/code&gt; property of the Cypress configuration file (&lt;code&gt;cypress.config.js&lt;/code&gt;).&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="nf"&gt;setupNodeEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;browsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;browsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;electron&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is, from the Cypress configuration, we are getting the browsers and filtering them for all except electron.&lt;/p&gt;

&lt;p&gt;In this way, when executing the &lt;code&gt;cypress open&lt;/code&gt; command, the Electron browser will no longer be available, as shown in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fzfkzmqfufkwss98ipjl2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzfkzmqfufkwss98ipjl2.png" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that way, we don't run the risk of accidentally testing the application in a browser that the real users of the application wouldn't use.&lt;/p&gt;




&lt;p&gt;For a real-world example, see the &lt;a href="https://github.com/wlsf82/meal-suggestion/blob/filter-browsers/cypress.config.js" rel="noopener noreferrer"&gt;&lt;strong&gt;following configuration file&lt;/strong&gt;&lt;/a&gt; from the &lt;a href="https://github.com/wlsf82/meal-suggestion/tree/filter-browsers" rel="noopener noreferrer"&gt;&lt;strong&gt;meal-suggestion&lt;/strong&gt;&lt;/a&gt; project on GitHub.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://docs.cypress.io/guides/guides/launching-browsers#Customize-available-browsers" rel="noopener noreferrer"&gt;https://docs.cypress.io/guides/guides/launching-browsers#Customize-available-browsers&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Curious and want to learn more about &lt;strong&gt;Cypress Testing Automation&lt;/strong&gt;? Check out my courses on &lt;a href="https://udemy.com/user/walmyr" rel="noopener noreferrer"&gt;&lt;strong&gt;Udemy&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;👋 Until next time, and happy testing!&lt;/p&gt;




&lt;p&gt;This post was originally published in Portuguese at the &lt;a href="https://talkingabouttesting.com/2023/08/01/filtrando-os-navegadores-disponiveis-ao-cypress/" rel="noopener noreferrer"&gt;&lt;strong&gt;Talking About Testing&lt;/strong&gt;&lt;/a&gt; blog.&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>testing</category>
      <category>javascript</category>
      <category>browsers</category>
    </item>
    <item>
      <title>Testing copy to clipboard with Cypress</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Fri, 09 Sep 2022 13:12:02 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/testing-copy-to-clipboard-with-cypress-1414</link>
      <guid>https://forem.com/walmyrlimaesilv/testing-copy-to-clipboard-with-cypress-1414</guid>
      <description>&lt;h2&gt;
  
  
  Learn how to read information saved in the browser window, such as what is held in the clipboard
&lt;/h2&gt;

&lt;p&gt;Imagine a simple application with only a text input field, with a default value of &lt;em&gt;Hello world&lt;/em&gt;, and a button called copy to clipboard, which, when clicked, copies the input text to that area, as the name suggests.&lt;/p&gt;

&lt;p&gt;When clicked as soon as the application is visited, the text copied is &lt;em&gt;Hello world&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;However, when such a field is cleared, another text is typed, and the button is clicked again, the new text is copied.&lt;/p&gt;

&lt;p&gt;And then you ask yourself.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How to test these scenario with &lt;a href="https://cypress.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;Cypress&lt;/strong&gt;&lt;/a&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Glad you asked because that's what I'm going to show you in this “Pinch of Cypress.”&lt;/p&gt;

&lt;p&gt;The application code is summarized in the following &lt;code&gt;index.html&lt;/code&gt; file.&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Copy to clipboard example page&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Copy to clipboard sample&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"copy-to-clipboard-input-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"copyToClipboard()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Copy to clipboard&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;copyToClipboard&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;copyText&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copy-to-clipboard-input-field&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nx"&gt;copyText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Select the text field&lt;/span&gt;
        &lt;span class="nx"&gt;copyText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSelectionRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99999&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// For mobile devices&lt;/span&gt;

        &lt;span class="c1"&gt;// Copy the text inside the text field&lt;/span&gt;
        &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;copyText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the test code in the following file &lt;code&gt;cypress/integration/copyToClipboard.spec.js&lt;/code&gt;.&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="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;copies the input field text to the clipboard&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Copy to clipboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertValueCopiedToClipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#copy-to-clipboard-input-field&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="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Foo bar baz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Copy to clipboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertValueCopiedToClipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Foo bar baz&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;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assertValueCopiedToClipboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;window&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&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;win&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readText&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;text&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the test, I first visit the application under test, i.e., the &lt;code&gt;index.html&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Then, I find the button with the text Copy to clipboard and click on it.&lt;/p&gt;

&lt;p&gt;When the button is clicked, the default text of the input field must be copied to the clipboard, and therefore, I verify that the correct value has been copied through a custom command, which I will explain later.&lt;/p&gt;

&lt;p&gt;Then I clear the input, type a different value and click the button again.&lt;/p&gt;

&lt;p&gt;Finally, I verify that the new value has now been copied to the clipboard, replacing the previous one.&lt;/p&gt;

&lt;p&gt;Now, let me explain in detail the custom command that verifies that the value was correctly copied to the clipboard.&lt;/p&gt;

&lt;p&gt;The command receives as an argument the &lt;code&gt;value&lt;/code&gt; to be compared, that is, the expected result.&lt;/p&gt;

&lt;p&gt;In its implementation, I execute the &lt;a href="https://on.cypress.io/window" rel="noopener noreferrer"&gt;&lt;code&gt;cy.window()&lt;/code&gt;&lt;/a&gt; command, in which I chain the &lt;a href="https://on.cypress.io/then" rel="noopener noreferrer"&gt;&lt;code&gt;.then()&lt;/code&gt;&lt;/a&gt; command, passing to it a callback function, which takes the browser window (&lt;code&gt;win&lt;/code&gt;) as an argument.&lt;/p&gt;

&lt;p&gt;With access to the window (&lt;code&gt;win&lt;/code&gt;), I access the &lt;code&gt;navigator&lt;/code&gt; property, from there I access the &lt;code&gt;clipboard&lt;/code&gt; property, and then I use the &lt;code&gt;readText()&lt;/code&gt; function to read the text copied to the clipboard, where I chain another &lt;code&gt;.then()&lt;/code&gt;, where in this case, the callback function receives the &lt;code&gt;text&lt;/code&gt; contained in the clipboard as an argument, allowing me to check that the &lt;code&gt;text&lt;/code&gt; is equal to the expected &lt;code&gt;value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And this is how I can test the value copied to the browser clipboard with Cypress.&lt;/p&gt;

&lt;p&gt;See the test running in the gif below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmq65tpjf2jsaxnwcgz11.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmq65tpjf2jsaxnwcgz11.gif" alt="Image description" width="600" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, see the complete code on &lt;a href="https://github.com/wlsf82/copy-to-clipboard" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Take the opportunity to leave it a ⭐!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Reference:&lt;/strong&gt; &lt;a href="https://www.w3schools.com/howto/howto_js_copy_clipboard.asp" rel="noopener noreferrer"&gt;https://www.w3schools.com/howto/howto_js_copy_clipboard.asp&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Did you like the content? Leave a comment.&lt;/p&gt;




&lt;p&gt;Curious and want to learn more about &lt;strong&gt;Cypress Testing Automation&lt;/strong&gt;? Check out my courses on &lt;a href="https://udemy.com/user/walmyr" rel="noopener noreferrer"&gt;&lt;strong&gt;Udemy&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;👋 Until next time, and happy testing!&lt;/p&gt;




&lt;p&gt;This post was originally published in Portuguese at the &lt;a href="https://talkingabouttesting.com/2022/06/06/testando-a-copia-para-a-area-de-transferencia-com-cypress/" rel="noopener noreferrer"&gt;&lt;strong&gt;Talking About Testing&lt;/strong&gt;&lt;/a&gt; blog.&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>testing</category>
      <category>clipboard</category>
      <category>automation</category>
    </item>
    <item>
      <title>cy.get() vs. cy.contains()</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Mon, 08 Aug 2022 19:29:00 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/a-simple-cypress-exercise-2lfe</link>
      <guid>https://forem.com/walmyrlimaesilv/a-simple-cypress-exercise-2lfe</guid>
      <description>&lt;h2&gt;
  
  
  Get to know one of the differences between the commands &lt;code&gt;cy.get&lt;/code&gt; and &lt;code&gt;cy.contains&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Here's a simple but helpful piece of information to better use &lt;a href="https://cypress.io" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; and understand when to use one command or another.&lt;/p&gt;

&lt;p&gt;Do you know the difference between the two lines of code below?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tr:contains(User 1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They look quite similar, don't they?&lt;/p&gt;

&lt;p&gt;However, they are actually different.&lt;/p&gt;

&lt;p&gt;While &lt;a href="https://docs.cypress.io/api/commands/get" rel="noopener noreferrer"&gt;&lt;code&gt;cy.get&lt;/code&gt;&lt;/a&gt; gets one &lt;strong&gt;or more&lt;/strong&gt; DOM elements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.cypress.io/api/commands/contains" rel="noopener noreferrer"&gt;&lt;code&gt;cy.contains&lt;/code&gt;&lt;/a&gt; gets &lt;strong&gt;only one&lt;/strong&gt; DOM element.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wlsf82/sum-table-rows-with-cypress/blob/users-logs/cypress/e2e/usersLogs.cy.js" rel="noopener noreferrer"&gt;Here's an example&lt;/a&gt; where we need to combine &lt;code&gt;cy.get&lt;/code&gt; with &lt;a href="https://api.jquery.com/contains-selector/" rel="noopener noreferrer"&gt;jQuery's &lt;code&gt;contains&lt;/code&gt;&lt;/a&gt; selector instead of using &lt;code&gt;cy.contains&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Just to reinforce.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tr:contains(User 1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// get ALL table rows which contain User 1 in their content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// get the first table row which contains User 1 in its content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope you find this helpful information.&lt;/p&gt;




&lt;p&gt;Did you like the content? Leave a comment.&lt;/p&gt;




&lt;p&gt;Curious and want to learn more about Cypress Testing Automation?&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://udemy.com/user/walmyr" rel="noopener noreferrer"&gt;my online courses on Udemy&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;👋 Until next time, and happy testing!&lt;/p&gt;




&lt;p&gt;This content was translated to Portuguese and can be found on the &lt;a href="https://talkingabouttesting.com/2022/08/08/cy-get-vs-cy-contains/" rel="noopener noreferrer"&gt;Talking About Testing blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>testing</category>
      <category>cyget</category>
      <category>cycontains</category>
    </item>
    <item>
      <title>How to login programmatically with Cypress</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Sun, 09 Jan 2022 23:42:57 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/how-to-login-programmatically-with-cypress-2iam</link>
      <guid>https://forem.com/walmyrlimaesilv/how-to-login-programmatically-with-cypress-2iam</guid>
      <description>&lt;h2&gt;
  
  
  Learn how to make your automated tests faster by authenticating via API
&lt;/h2&gt;

&lt;p&gt;Automated graphical user interface tests must be independent of each other. In addition, such tests must relly as little as possible on the graphical user interface to reach the desired state for the test itself to take place.&lt;/p&gt;

&lt;p&gt;It seems counter-intuitive, but that's precisely it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;From the graphical user interface, we should test it only once. More than that is waste.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, in most web applications, the user must be authenticated to access certain functionality. So, how to authenticate such a user without going through the login page?&lt;/p&gt;

&lt;p&gt;That's precisely what I will show you in this &lt;strong&gt;pinch of Cypress&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; It is worth remembering that this is just an alternative and that it may not be suitable for your use case. For more examples, I recommend reading the &lt;strong&gt;Testing Strategies&lt;/strong&gt; section of the &lt;a href="https://docs.cypress.io/guides/overview/why-cypress" rel="noopener noreferrer"&gt;&lt;strong&gt;Cypress official documentation&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To ease the explanation, I will use a project I have recently contributed to — the &lt;a href="https://www.brmodeloweb.com/lang/en/index.html" rel="noopener noreferrer"&gt;&lt;strong&gt;BR Modelo Web&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's imagine the following test case.&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;// cypress/e2e/programmaticLogin.cy.js&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;successfully logs in programmatically&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apiUrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/models?userId=*`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getUserModels&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apiUrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/users/login`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userEmail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userPassword&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;body&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sessionId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/#!/main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@getUserModels&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Models&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's understand what this code does.&lt;/p&gt;

&lt;p&gt;First, inside the test body, that is, inside the &lt;code&gt;it&lt;/code&gt; block, I use the &lt;a href="https://docs.cypress.io/api/commands/intercept" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;cy.intercept&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; command. With such a command, I can “listen” 👂 to network calls, such as a &lt;code&gt;GET&lt;/code&gt; request to the application's API URL that fetches the models of the logged-in user. Then I give an alias to that intercept. The alias is &lt;code&gt;getUserModels&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then comes the part where the programmatic authentication happens.&lt;/p&gt;

&lt;p&gt;In this part, I use the &lt;a href="https://docs.cypress.io/api/commands/request" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;cy.request&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; functionality to make a &lt;code&gt;POST&lt;/code&gt; request to the login URL, passing the username and password properties in the request &lt;code&gt;body&lt;/code&gt;, both coming from variables (using the &lt;a href="https://docs.cypress.io/api/cypress-api/env" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;Cypress.env()&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; functionality). I do this not to expose sensitive data.&lt;/p&gt;

&lt;p&gt;Then, I chain to the &lt;code&gt;cy.request()&lt;/code&gt; command a &lt;a href="https://docs.cypress.io/api/commands/then" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;.then()&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;, which takes as argument an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" rel="noopener noreferrer"&gt;&lt;strong&gt;arrow function&lt;/strong&gt;&lt;/a&gt;, which takes as an argument the response's body of the &lt;code&gt;cy.request()&lt;/code&gt;, using JavaScript's object destructuring.&lt;/p&gt;

&lt;p&gt;In the body of this arrow function, I use the &lt;a href="https://docs.cypress.io/api/commands/setcookie" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;cy.setCookie()&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; functionality, as the name suggests, to set some cookies based on the &lt;code&gt;body&lt;/code&gt; of the request-response. These are precisely the cookies set when the user logs in via the graphical user interface.&lt;/p&gt;

&lt;p&gt;With cookies set, I visit the application's homepage.&lt;/p&gt;

&lt;p&gt;Finally, I do some checks.&lt;/p&gt;

&lt;p&gt;First, I wait for the intercept request created earlier to occur, with &lt;a href="https://docs.cypress.io/api/commands/wait" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;cy.wait()&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;, passing it the alias created earlier (&lt;code&gt;'@getUserModels'&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;And then, I check that a particular element is visible (an &lt;code&gt;h2&lt;/code&gt; with the text Models), which is only visible to authenticated users, proving that the login was successful.&lt;/p&gt;

&lt;p&gt;Done! 🎉&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attention:&lt;/strong&gt; When testing a login functionality, it is recommended that such testing takes place via the graphical user interface. However, for all other features that require the authenticated user, use login programmatically and save a few seconds on each test!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Bonus - &lt;a href="https://docs.cypress.io/api/cypress-api/custom-commands" rel="noopener noreferrer"&gt;Custom Command&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Since more than one test suite will need to login programmatically, we can move that logic to a custom command, which can be reused as many times as needed.&lt;/p&gt;

&lt;p&gt;Here's what the test code would look like.&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;// cypress/e2e/programmaticLogin.cy.js&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;successfully logs in via GUI&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apiUrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/models?userId=*`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getUserModels&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loginViaAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@getUserModels&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Models&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the custom command.&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;// cypress/support/commands.js&lt;/span&gt;

&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loginViaAPI&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userEmail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userPassword&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apiUrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/users/login`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;body&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sessionId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/#!/main&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="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the test, now all the logic of &lt;code&gt;cy.request&lt;/code&gt; and &lt;code&gt;cy.setCookie&lt;/code&gt; is abstracted. I just call the &lt;code&gt;cy.loginViaAPI()&lt;/code&gt; command, and it manages to do what needs to be done to authenticate the user.&lt;/p&gt;

&lt;p&gt;In addition to having the previous logic of programmatic login, the custom command can now also receive an email and password as arguments. However, if no arguments are passed, such values already have defaults coming from variables.&lt;/p&gt;

&lt;p&gt;Also, I decided to move the visit to the home page to the custom command.&lt;/p&gt;

&lt;p&gt;See the test running and authenticating without going through the login page. It looks like magic! 🪄&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F4uolfkeca3igt60e8pda.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F4uolfkeca3igt60e8pda.gif" alt="Image description" width="1665" height="960"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;I hope you enjoyed it.&lt;/p&gt;




&lt;p&gt;Access the final version in this &lt;a href="https://github.com/wlsf82/programmatic-login-with-cypress" rel="noopener noreferrer"&gt;&lt;strong&gt;public repository&lt;/strong&gt;&lt;/a&gt; on my GitHub profile.&lt;/p&gt;

&lt;p&gt;Or the &lt;a href="https://github.com/brmodeloweb/brmodelo-app" rel="noopener noreferrer"&gt;&lt;strong&gt;BR Modelo Web App&lt;/strong&gt;&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;Take the opportunity to leave a star! ⭐&lt;/p&gt;




&lt;p&gt;Did you like the content? Leave a comment.&lt;/p&gt;




&lt;p&gt;Curious and want to learn more about &lt;strong&gt;Cypress Testing Automation&lt;/strong&gt;? Check out my courses on &lt;a href="https://udemy.com/user/walmyr" rel="noopener noreferrer"&gt;&lt;strong&gt;Udemy&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;👋 Until next time and happy testing!&lt;/p&gt;




&lt;p&gt;This post was originally published in Portuguese at the &lt;a href="https://talkingabouttesting.com/2021/12/14/como-fazer-login-de-forma-programatica-com-cypress/" rel="noopener noreferrer"&gt;&lt;strong&gt;Talking About Testing&lt;/strong&gt;&lt;/a&gt; blog.&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>testing</category>
      <category>authentication</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The importance of testability for web testing automation</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Fri, 07 Jan 2022 16:39:22 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/the-importance-of-testability-for-web-testing-automation-5f18</link>
      <guid>https://forem.com/walmyrlimaesilv/the-importance-of-testability-for-web-testing-automation-5f18</guid>
      <description>&lt;h2&gt;
  
  
  Learn how to improve the readability of automated tests written with the Cypress framework
&lt;/h2&gt;

&lt;p&gt;Does your team care about testability?&lt;/p&gt;

&lt;p&gt;If so, this post is for you!&lt;/p&gt;

&lt;p&gt;One way to check the testability of a web application is to inspect the frontend elements and verify if they have attributes added specifically to facilitate the automation of graphical interface tests, such as &lt;code&gt;data-test&lt;/code&gt;, &lt;code&gt;data-test-id&lt;/code&gt;, &lt;code&gt;data-qa&lt;/code&gt;, &lt;code&gt;data-cy&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Imagine the following HTML form.&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="c"&gt;&amp;lt;!-- ./index.html --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"login-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;"email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email&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;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;data-test=&lt;/span&gt;&lt;span class="s"&gt;"email-field"&lt;/span&gt; &lt;span class="na"&gt;required&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;"password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Password&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;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;data-test=&lt;/span&gt;&lt;span class="s"&gt;"password-field"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="nt"&gt;/&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="na"&gt;data-test=&lt;/span&gt;&lt;span class="s"&gt;"login-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/button&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;As you can see, all the elements we need to automate such a form have &lt;code&gt;data-test&lt;/code&gt; attributes.&lt;/p&gt;

&lt;p&gt;This is an example of &lt;strong&gt;testability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And why is this important?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;When the frontend of a web application has attributes specifically created for testability purposes, there is less risk that changes to its logic or style will break the tests.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, let's look at a test (written with &lt;a href="https://cypress.io" rel="noopener noreferrer"&gt;&lt;strong&gt;Cypress&lt;/strong&gt;&lt;/a&gt;) that fills out such a form.&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;// cypress/integration/loginForm.spec.js&lt;/span&gt;

&lt;span class="nf"&gt;beforeEach&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&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="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;successfully logs in&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userEmail&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;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userPassword&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-test="email-field"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-test="password-field"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-test="login-button"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;re now logged in!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test above makes use of such attributes, however, there is some repetition in the selection of elements, where the only part that changes are the values of the &lt;code&gt;data-test&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;What if we could improve this?&lt;/p&gt;

&lt;p&gt;Well, we can!&lt;/p&gt;

&lt;p&gt;See the new version of the test below.&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;// cypress/integration/loginForm.spec.js&lt;/span&gt;

&lt;span class="nf"&gt;beforeEach&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.html&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="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;successfully logs in&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userEmail&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;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userPassword&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email-field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password-field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;login-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;re now logged in!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&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;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dataTest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[data-test="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"]`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, instead of all that repetition, we have a custom command that abstracts this logic, and the test itself is clean, passing to the &lt;code&gt;.dataTest&lt;/code&gt; command the appropriate value depending on the element we want to select.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Ideally, such custom command would be defined in the &lt;code&gt;cypress/support/commands.js&lt;/code&gt; file, however, in this case I left it directly in the test file for teaching purposes.&lt;/p&gt;

&lt;p&gt;See the test running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F66olj8cd7p53leytae0z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F66olj8cd7p53leytae0z.gif" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it!&lt;/p&gt;




&lt;p&gt;Did you like the content? Leave a comment.&lt;/p&gt;

&lt;p&gt;Also, access the &lt;a href="https://github.com/wlsf82/cy-data-test" rel="noopener noreferrer"&gt;&lt;strong&gt;complete code on GitHub&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Curious and want to learn more about &lt;strong&gt;Cypress Testing Automation&lt;/strong&gt;? Check out my courses on &lt;a href="https://udemy.com/user/walmyr" rel="noopener noreferrer"&gt;&lt;strong&gt;Udemy&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;👋 Until next time and happy testing!&lt;/p&gt;




&lt;p&gt;This post was originally published in Portuguese at the &lt;a href="https://talkingabouttesting.com/2022/01/06/a-importancia-da-testabilidade-para-testes-automatizados-web/" rel="noopener noreferrer"&gt;&lt;strong&gt;Talking About Testing&lt;/strong&gt;&lt;/a&gt; blog.&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>testing</category>
      <category>webtesting</category>
      <category>testability</category>
    </item>
    <item>
      <title>How to create fixtures with random data using Cypress and faker</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Wed, 13 Oct 2021 10:26:13 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/how-to-create-fixtures-with-random-data-using-cypress-and-faker-46cl</link>
      <guid>https://forem.com/walmyrlimaesilv/how-to-create-fixtures-with-random-data-using-cypress-and-faker-46cl</guid>
      <description>&lt;h2&gt;
  
  
  Random fixtures? Yes, it is possible!
&lt;/h2&gt;

&lt;p&gt;One of these days, in the &lt;a href="https://t.me/cypress_br" rel="noopener noreferrer"&gt;&lt;strong&gt;Cypress-BR&lt;/strong&gt;&lt;/a&gt; group on Telegram, the following question came up:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is it possible to put &lt;code&gt;faker&lt;/code&gt; on a &lt;code&gt;.json&lt;/code&gt; file?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The short answer is no.&lt;/p&gt;

&lt;p&gt;But, it's possible to create a &lt;code&gt;.json&lt;/code&gt; file dynamically, using the &lt;a href="https://docs.cypress.io/api/commands/writefile#JSON" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;cy.writeFile&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; functionality, and with the help of the &lt;a href="https://fakerjs.dev" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;faker&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; library, make all data in this file dynamic.&lt;/p&gt;

&lt;p&gt;Let's look at an example, creating a &lt;a href="https://docs.cypress.io/api/commands/fixture#JSON" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;fixture&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; for use in a test that mocks the backend and tests the frontend in isolation.&lt;/p&gt;

&lt;p&gt;The application under test (AUT) is called &lt;a href="https://wlsf82-hacker-stories.web.app/" rel="noopener noreferrer"&gt;&lt;strong&gt;Hacker Stories&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This application communicates with the &lt;a href="https://hn.algolia.com/api" rel="noopener noreferrer"&gt;&lt;strong&gt;Hackernews public API&lt;/strong&gt;&lt;/a&gt; for listing stories.&lt;/p&gt;

&lt;p&gt;However, as mentioned earlier, we will mock the API.&lt;/p&gt;

&lt;p&gt;The test file is as follows.&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;// cypress/integration/hackerStories.spec.js&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hacker Stories&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="nf"&gt;beforeEach&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateFixture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/search?query=React&amp;amp;page=0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stories&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;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getStories&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@getStories&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="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 20 stories, then 19 when dismissing one&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;have.length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&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-small&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;have.length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&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;Note that in the &lt;code&gt;beforeEach&lt;/code&gt; hook, there is a custom command called &lt;code&gt;generateFixture()&lt;/code&gt;. We'll see what this command does in a moment.&lt;/p&gt;

&lt;p&gt;Also, notice that we are intercepting a request, which we will respond with a fixture called &lt;code&gt;stories&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Afterward, we visit the AUT, wait for such mocked request to happen, and the test is executed, which verifies that there are 20 items in the list and that when removing the first one, 19 are left.&lt;/p&gt;

&lt;p&gt;You might be curious about the implementation of the &lt;code&gt;generateFixture()&lt;/code&gt; command, right?&lt;/p&gt;

&lt;p&gt;There it goes.&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;// cypress/support/commands.js&lt;/span&gt;

&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;generateFixture&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;faker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@faker-js/faker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cypress/fixtures/stories.json&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lorem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;num_comments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;datatype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;points&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;datatype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;objectID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;datatype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the random data, we import &lt;code&gt;faker&lt;/code&gt; to the command, using JavaScript's &lt;code&gt;require&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Then we use &lt;code&gt;cy.writeFile&lt;/code&gt;, to write a file called &lt;code&gt;stories.json&lt;/code&gt; in the &lt;code&gt;cypress/fixtures/&lt;/code&gt; directory. As a second argument, we pass an object, which will contain the value of that file.&lt;/p&gt;

&lt;p&gt;Such an object will have a &lt;code&gt;hits&lt;/code&gt; property, which is exactly what the frontend expects, and that property expects an array of objects.&lt;/p&gt;

&lt;p&gt;We use lodash's &lt;a href="https://lodash.com/docs/4.17.15#times" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;.times&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; functionality (which is bundled with Cypress), as it returns precisely an array.&lt;/p&gt;

&lt;p&gt;Then the &lt;code&gt;.times&lt;/code&gt; function runs 20 times to create 20 random stories, each with its &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;, &lt;code&gt;author&lt;/code&gt;, &lt;code&gt;num_comments&lt;/code&gt;, &lt;code&gt;points&lt;/code&gt;, and &lt;code&gt;objectID&lt;/code&gt;, using different functionalities offered by the &lt;code&gt;faker&lt;/code&gt; library.&lt;/p&gt;

&lt;p&gt;For an example of the created fixture, access &lt;a href="https://github.com/wlsf82/dynamic-fixtures/blob/main/cypress/fixtures/example.json" rel="noopener noreferrer"&gt;&lt;strong&gt;this file&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Since this fixture is dynamic, we must add it to the &lt;a href="https://github.com/wlsf82/dynamic-fixtures/blob/main/.gitignore#L3" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;.gitignore&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; file, cause we don't want to version it.&lt;/p&gt;

&lt;p&gt;And so, we have a test that consumes a dynamically created fixture with random data. 🥳&lt;/p&gt;

&lt;p&gt;That is, for each run, the fixture will be overwritten with new data.&lt;/p&gt;




&lt;p&gt;I invite you to clone the project on your computer, install the dependencies following the documentation and then run the tests (both in interactive and in headless mode).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wlsf82/dynamic-fixtures" rel="noopener noreferrer"&gt;&lt;strong&gt;Access the complete project on GitHub&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Take the opportunity to leave a ⭐.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note 2:&lt;/strong&gt; As an alternative to the proposed solution, check out &lt;a href="https://github.com/wlsf82/dynamic-fixtures/commit/f8925dbfd6186cbc8c09eda1b2c85d6b48996296" rel="noopener noreferrer"&gt;&lt;strong&gt;this other one&lt;/strong&gt;&lt;/a&gt;, where instead of using fixtures, we overwrite the request response's body.&lt;/p&gt;




&lt;p&gt;Did you like the content? Leave a comment!&lt;/p&gt;




&lt;p&gt;Curious and want to learn more about &lt;strong&gt;Cypress Testing Automation&lt;/strong&gt;? Check out my courses on &lt;a href="https://udemy.com/user/walmyr" rel="noopener noreferrer"&gt;&lt;strong&gt;Udemy&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;👋 Until next time and happy testing!&lt;/p&gt;




&lt;p&gt;This post was originally published in Portuguese at the &lt;a href="https://talkingabouttesting.com/2021/09/13/como-criar-fixtures-com-dados-aleatorios-com-cypress-e-faker/" rel="noopener noreferrer"&gt;&lt;strong&gt;Talking About Testing&lt;/strong&gt;&lt;/a&gt; blog.&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>fixtures</category>
      <category>testing</category>
      <category>faker</category>
    </item>
    <item>
      <title>Best practices in test automation with Cypress</title>
      <dc:creator>Walmyr</dc:creator>
      <pubDate>Mon, 27 Sep 2021 05:50:01 +0000</pubDate>
      <link>https://forem.com/walmyrlimaesilv/best-practices-in-test-automation-with-cypress-49ee</link>
      <guid>https://forem.com/walmyrlimaesilv/best-practices-in-test-automation-with-cypress-49ee</guid>
      <description>&lt;p&gt;On July 31, 2021, I had the pleasure of participating in the &lt;a href="https://minastestingconference.com.br" rel="noopener noreferrer"&gt;&lt;strong&gt;Minas Testing Conference&lt;/strong&gt;&lt;/a&gt;, where I spoke about &lt;a href="https://youtu.be/iXFVV76YnRQ?t=106" rel="noopener noreferrer"&gt;&lt;strong&gt;How to create fast and robust automated tests with Cypress&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The lecture was in Portuguese.&lt;/p&gt;

&lt;p&gt;The talk was really cool, and I brought you a summary with each of the best practices, so you can apply it to your projects and make your tests faster and more robust.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note 2:&lt;/strong&gt; You can apply most of the best practices mentioned below regardless of the test framework being used, but some are specific to Cypress.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Independent tests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Automated tests must run in isolation, without the need for another test to run to create some state in the application under test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The failure of one test shouldn't impact the results of other tests.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In addition, independent tests are easier to parallelize.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; use the &lt;code&gt;beforeEach&lt;/code&gt; hook when you need to perform repeated steps for all tests of a given &lt;code&gt;describe&lt;/code&gt; or &lt;code&gt;context&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Programmatic authentication&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Logging in via the graphical user interface as a pre-condition for all tests is costly (in terms of execution time), and it makes the tests dependent on each other, which is a bad practice.&lt;/p&gt;

&lt;p&gt;A disabled login button due to an HTML error, for example, shouldn't break an entire test suite.&lt;/p&gt;

&lt;p&gt;By adding &lt;a href="https://docs.cypress.io/api/commands/session" rel="noopener noreferrer"&gt;&lt;strong&gt;mechanisms to log in programmatically&lt;/strong&gt;&lt;/a&gt;, you make tests faster and more independent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. State creation mechanisms&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By creating such mechanisms, we ensure that tests are completely decoupled from each other, we don't need abstractions that add complexity to tests, such as Page Objects, and we guarantee fast and straight-to-the-point tests.&lt;/p&gt;

&lt;p&gt;Examples of these mechanisms are API calls for creating resources, communication with the database via tasks, or running scripts at the operating system level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. &lt;code&gt;data-*&lt;/code&gt; attributes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Adding attributes to front-end elements, such as &lt;code&gt;data-test&lt;/code&gt;, &lt;code&gt;data-testid&lt;/code&gt;, or &lt;code&gt;data-cy&lt;/code&gt;, adds to the application what I call "&lt;strong&gt;testability&lt;/strong&gt;," as these attributes are specifically created for testing purposes, decreasing the chances of front-end changes break the tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Don't do this: &lt;code&gt;var el = cy.get('selector')&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Remember. Cypress is not Selenium! 😅&lt;/p&gt;

&lt;p&gt;Cypress has its own architecture, where although in many cases it allows writing code that seems synchronous, even if it is asynchronous (since it puts each command in a queue for later execution), it is not possible to do something like:&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;myBtn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;myBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, you can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myBtn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@myBtn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Most of Cypress's commands are chainable!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Do not test external applications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Relying on Google's GUI login for your tests or some third-party API can make your tests unstable, as changes to these services (which you don't control) will break your tests, even if it's all right "on your side."&lt;/p&gt;

&lt;p&gt;To ensure that such services are in line with your application, you can have a smoke-test suite, for example, or contract tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Tests too small or too large&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;End-to-end tests are not unit tests. Due to the cost of running them, it's worth adding more than one assertion per test to save time.&lt;/p&gt;

&lt;p&gt;However, beware of extensive tests. Maybe these are testing a lot of unrelated things and could be broken down into smaller ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Do not use the &lt;code&gt;after&lt;/code&gt; and &lt;code&gt;afterEach&lt;/code&gt; hooks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If something goes wrong during the execution of the tests, such hooks run the risk of not being executed, leaving "junk" in the application.&lt;/p&gt;

&lt;p&gt;As a good practice, do any cleanup before running the tests, using the &lt;code&gt;beforeEach&lt;/code&gt; hook, for example.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Do not use &lt;code&gt;cy.wait(Number)&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cypress already has automatic waiting with different default timeouts to wait for elements to be visible, for animations to end, for requests to be sent and responded and for pages to be loaded.&lt;/p&gt;

&lt;p&gt;What you can do to make your tests even more robust is wait for elements to be visible:&lt;/p&gt;

&lt;p&gt;E.g.: &lt;code&gt;cy.get('[data-cy="avatar"]').should('be.visible')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Or, you can wait for a particular request that you gave an alias to finish.&lt;/p&gt;

&lt;p&gt;E.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(...).&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myReq&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;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@myReq&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wrote about it on &lt;a href="https://dev.to/walmyrlimaesilv/cy-request-vs-cy-intercept-cmi"&gt;&lt;strong&gt;&lt;code&gt;cy.request&lt;/code&gt; vs. &lt;code&gt;cy.intercept&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. &lt;code&gt;start-server-and-test&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use mechanisms such as the &lt;a href="https://www.npmjs.com/package/start-server-and-test" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;start-server-and-test&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; library to initialize the application server before running the tests, ensuring that it will run with the correct code and that the tests will only run when the application is responding.&lt;/p&gt;

&lt;p&gt;Besides, such an approach will help you run your tests on a &lt;a href="https://docs.cypress.io/guides/continuous-integration/introduction" rel="noopener noreferrer"&gt;&lt;strong&gt;Continuous Integration&lt;/strong&gt;&lt;/a&gt; server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11. Set the &lt;code&gt;baseUrl&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By setting the &lt;code&gt;baseUrl&lt;/code&gt; in the configuration file (&lt;code&gt;cypress.json&lt;/code&gt;), your tests can visit pages via relative URLs, making them cleaner.&lt;/p&gt;

&lt;p&gt;In addition, the &lt;code&gt;baseUrl&lt;/code&gt; can be overwritten via a &lt;code&gt;cypress.env.json&lt;/code&gt; file, environment variables (&lt;code&gt;CYPRESS_*&lt;/code&gt;), command line, plugins, etc., making it possible to run the same tests against different environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By following these best practices, you will have fast and robust tests that your team trusts and helps to maintain and evolve.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>cypress</category>
      <category>e2etesting</category>
      <category>bestpractices</category>
    </item>
  </channel>
</rss>
