<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahsan Bilal</title>
    <description>The latest articles on DEV Community by Ahsan Bilal (@ahsanbilal).</description>
    <link>https://dev.to/ahsanbilal</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%2F568971%2Ffbdba40a-2ed8-4794-8ab4-2b1917150eea.jpg</url>
      <title>DEV Community: Ahsan Bilal</title>
      <link>https://dev.to/ahsanbilal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahsanbilal"/>
    <language>en</language>
    <item>
      <title>Key Hacks for Testers: Unleashing the Power of the Network Tab in Your Browser</title>
      <dc:creator>Ahsan Bilal</dc:creator>
      <pubDate>Fri, 19 May 2023 20:00:30 +0000</pubDate>
      <link>https://dev.to/ahsanbilal/key-hacks-for-testers-unleashing-the-power-of-the-network-tab-in-your-browser-2lb9</link>
      <guid>https://dev.to/ahsanbilal/key-hacks-for-testers-unleashing-the-power-of-the-network-tab-in-your-browser-2lb9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As a tester, your role is crucial in ensuring the quality and functionality of web applications. One indispensable tool at your disposal is the Network tab in your browser’s developer tools. This powerful feature enables you to monitor and manipulate network requests, analyse performance, and detect potential issues. In this article, we will explore some key hacks for testers, empowering you to make the most of the Network tab and enhance your testing capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the Network Tab
&lt;/h3&gt;

&lt;p&gt;The Network tab is a part of the developer tools provided by modern web browsers. To access it, simply right-click anywhere on a webpage, select “Inspect” or “Inspect Element,” and navigate to the “Network” tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rIayfsof--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rogcs8yrj4ecunes9a1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rIayfsof--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rogcs8yrj4ecunes9a1.png" alt="Image description" width="209" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This tab displays all the network requests made by the web page, including HTTP requests, responses, and associated details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring Network Requests &amp;amp; Analysing Performance
&lt;/h3&gt;

&lt;p&gt;By monitoring network requests, you gain valuable insights into the behaviour and performance of a web application. The Network tab displays various columns, such as URL, status code, size, and timing, enabling you to track individual requests. You can filter requests based on specific criteria, such as file type or response code, to focus on relevant data.&lt;/p&gt;

&lt;p&gt;The Network tab also allows you to evaluate the performance of web pages and identify potential bottlenecks. By examining the timing information, you can pinpoint requests that contribute to slow loading times. Look for requests with long “Waiting” or “Content Download” times, which may indicate areas for optimisation. Additionally, the waterfall view provides a visual representation of request timings, aiding in performance analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iGnMvSSD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/650qjw12bzqkyd1yspvj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iGnMvSSD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/650qjw12bzqkyd1yspvj.png" alt="Image description" width="800" height="705"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspecting Request and Response Headers
&lt;/h3&gt;

&lt;p&gt;Request and response headers contain vital information exchanged between the client and the server. In the Network tab, you can inspect headers to understand how requests are made and how servers respond. This is particularly useful when testing APIs or troubleshooting authentication issues. Look for specific headers, such as “Authorisation” or “Content-Type,” to ensure correct configurations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--29nHStfT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7z263v54tivax7xk7io.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--29nHStfT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7z263v54tivax7xk7io.png" alt="Image description" width="800" height="776"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Manipulating Requests
&lt;/h3&gt;

&lt;p&gt;The Network tab empowers testers to manipulate network requests, enabling them to simulate different scenarios and edge cases. For example, you can modify request headers, such as User-Agent or Referer, to mimic different user agents or referrers (also called user-agent spoofing). You can also modify request payloads or parameters to test specific conditions or validate input sanitisation. These manipulations help uncover vulnerabilities and assess the resilience of the application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4HpreZyP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5nnp8p7es03t81xkw6c8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4HpreZyP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5nnp8p7es03t81xkw6c8.png" alt="Image description" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Capturing Network Traffic
&lt;/h3&gt;

&lt;p&gt;In certain testing scenarios, capturing network traffic becomes essential for thorough analysis. The Network tab allows you to save all requests and responses as a HAR (HTTP Archive) file. This file contains a detailed record of the network activity, including headers, timings, and content. By capturing network traffic, you can reproduce issues, share findings with developers, or preserve evidence for further investigation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BFq5WWZI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/64swrkzb5o89q79yw43s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BFq5WWZI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/64swrkzb5o89q79yw43s.png" alt="Image description" width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Simulating Network Conditions
&lt;/h3&gt;

&lt;p&gt;Testing under different network conditions is crucial to ensure optimal performance across various environments. The Network tab provides built-in options to simulate network conditions, such as throttling the network speed or introducing latency. By mimicking slow or unreliable network connections, you can observe how the application behaves in real-world scenarios and address any performance issues accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zqqK2Y-a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4tiqk1q5qxnzsxazfjmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zqqK2Y-a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4tiqk1q5qxnzsxazfjmd.png" alt="Image description" width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Leveraging Performance Analysis Tools
&lt;/h3&gt;

&lt;p&gt;To initiate performance recording, simply click the “Measure page load” button in DevTools. The page will reload, and the recording will automatically stop a few seconds after the page has finished loading.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dsu4cNUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y0kr14xtpxvymgobdtss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dsu4cNUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y0kr14xtpxvymgobdtss.png" alt="Image description" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Among the standout functionalities of Performance Insights, the playback feature stands out as one of the most remarkable. It enables you to not only replay the entire performance recording but also delve into specific moments within the record by zooming in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qG0wn8KQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hdyfigy8bb44ct7a87ka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qG0wn8KQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hdyfigy8bb44ct7a87ka.png" alt="Image description" width="800" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What amplifies its effectiveness further is its seamless alignment with the tasks being carried out by the browser in real-time, such as network requests and rendering. This visual correlation enhances the overall power and usability of the feature.&lt;/p&gt;

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

&lt;p&gt;The Network tab in your browser’s developer tools is an essential tool for testers, offering a wide range of features to analyse, monitor, and manipulate network requests. By mastering its capabilities and implementing the hacks discussed in this article, you can enhance your testing skills, uncover hidden issues, and contribute to the overall quality of web applications.&lt;/p&gt;

&lt;p&gt;By embracing the power of the Network tab and continuously acquiring new skills, you become an invaluable asset in ensuring the quality and functionality of web applications. Unlock a world of possibilities for comprehensive and effective testing. Happy testing!&lt;/p&gt;




&lt;p&gt;If you liked this, click ❤ so other people will also notice here.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>cybersecurity</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Mastering Advanced Cypress.io Test Automation [Part 4/4]: Writing Custom Functions</title>
      <dc:creator>Ahsan Bilal</dc:creator>
      <pubDate>Fri, 12 May 2023 01:47:05 +0000</pubDate>
      <link>https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-44-writing-custom-functions-5bkp</link>
      <guid>https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-44-writing-custom-functions-5bkp</guid>
      <description>&lt;p&gt;By the end of this part, you’ll be proficient in writing custom functions for your Cypress.io test suite, paving the way to advanced test automation. So, let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Custom Functions in Cypress.io
&lt;/h2&gt;

&lt;p&gt;Before we dive into the code, let’s first understand what custom functions are in the context of Cypress.io.&lt;/p&gt;

&lt;p&gt;While Cypress.io provides many built-in commands to interact with web elements, there may be situations where you need to perform more complex actions or write custom assertions. Fortunately, Cypress.io allows you to create your own custom functions that extend the functionality of Cypress.io. They can be used to perform specific tasks that are not natively supported by Cypress.io, or to simplify the code and make it more readable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing a Custom Function in Cypress.io [Example-1]
&lt;/h3&gt;

&lt;p&gt;Now that we understand what custom functions are, let’s move on to writing one. In this example, we’ll create a custom function to generate random usernames.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function generateRandomUsername() {
  let text = "";
  let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  for (let i = 0; i &amp;lt; 8; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }

  return "user_" + text;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s break down the code above. The &lt;code&gt;generateRandomUsername&lt;/code&gt; function takes no parameters and returns a string value. It starts by declaring two variables &lt;code&gt;text&lt;/code&gt; and &lt;code&gt;possible&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;text&lt;/code&gt; is initially an empty string, and &lt;code&gt;possible&lt;/code&gt; contains all the possible characters that can be used to generate the random string.&lt;/p&gt;

&lt;p&gt;Next, a &lt;code&gt;for&lt;/code&gt; loop is used to iterate 8 times, and in each iteration, a random character is selected from the &lt;code&gt;possible&lt;/code&gt; string using the &lt;code&gt;Math.random()&lt;/code&gt; function. The selected character is then appended to the text string.&lt;/p&gt;

&lt;p&gt;Finally, the function returns a string value by concatenating the &lt;code&gt;text&lt;/code&gt; string with the prefix “user_”.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the Custom Function [Example-1] in a Test Case
&lt;/h3&gt;

&lt;p&gt;Now that we have our custom function, let’s use it in a test case. In this example, we’ll use the custom function to generate a random username and fill it in a registration form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('registers a new user with a random username', () =&amp;gt; {
  const username = generateRandomUsername();

  cy.visit('https://example.com/register')
  cy.get('#username').type(username)
  cy.get('#email').type('test@example.com')
  cy.get('#password').type('password123')
  cy.get('#submit').click()

  cy.contains('Registration successful!')
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test case above starts by generating a random username using our custom function &lt;code&gt;generateRandomUsername()&lt;/code&gt;. We then visit the registration page and use the &lt;code&gt;cy.get()&lt;/code&gt; command to select the &lt;code&gt;#username&lt;/code&gt;, &lt;code&gt;#email&lt;/code&gt;, &lt;code&gt;#password&lt;/code&gt;, and &lt;code&gt;#submit&lt;/code&gt; elements on the page. We fill in the form fields with our test data and click the submit button.&lt;/p&gt;

&lt;p&gt;Finally, we assert that the registration was successful by checking for the presence of the success message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing a Custom Function in Cypress.io [Example-2]
&lt;/h3&gt;

&lt;p&gt;Let’s say you need to check that a particular element is visible on the page and has a certain size. You could write a custom function that encapsulates this logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cypress.Commands.add('assertElementIsVisibleAndHasSize', (selector, width, height) =&amp;gt; {
  cy.get(selector).should('be.visible').and(($el) =&amp;gt; {
    expect($el.width()).to.equal(width)
    expect($el.height()).to.equal(height)
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we’re defining a custom command using the &lt;code&gt;Cypress.Commands.add()&lt;/code&gt; method. Our command takes three parameters: the selector for the element, the expected width, and the expected height. We then use the &lt;code&gt;cy.get()&lt;/code&gt; command to select the element and chain the &lt;code&gt;.should()&lt;/code&gt; method to check that it is visible. Finally, we use the &lt;code&gt;.and()&lt;/code&gt; method to perform additional assertions on the element’s width and height.&lt;/p&gt;

&lt;p&gt;Now, you can use this custom command in your tests just like any other Cypress.io command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('Checks the size of a visible element', () =&amp;gt; {
  cy.visit('https://www.example.com')
  cy.assertElementIsVisibleAndHasSize('.my-element', 100, 200)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Here we’ve seen how to write custom functions in Cypress.io to extend the functionality of the framework and tackle complex test automation scenarios. We’ve provided a detailed explanation of each line of code, how it differs from basic test-case examples, and how to overcome common complications. By using custom functions, you can make your test code more readable, maintainable, and reusable. Custom functions can help you simplify complex test cases, handle dynamic data, and reduce code duplication.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you liked this, click ❤ so other people will also notice here.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-world Examples
&lt;/h2&gt;

&lt;p&gt;While the examples we’ve provided in this series of advanced and complicated topics are useful for learning how to handle iframes, network stubbing, promise resolving, and custom functions, they are somewhat contrived. To truly master these techniques, it’s important to see how they can be applied in real-world scenarios.&lt;/p&gt;

&lt;p&gt;For example, let’s say you’re testing an e-commerce website that uses iframes to display product information from a third-party vendor. You might need to test that the correct product information is being displayed in the iframe, and that users can interact with the product options and add the product to their cart.&lt;/p&gt;

&lt;p&gt;Similarly, let’s say you’re testing a social media application that relies heavily on network requests to display user content. You might need to use network stubbing to simulate slow network connections or error responses, and test how the application handles these situations.&lt;/p&gt;

&lt;p&gt;Finally, let’s say you’re testing a financial application that requires complex interactions with web elements. You might need to write custom functions to perform calculations or validate that certain financial data is being displayed correctly.&lt;/p&gt;

&lt;p&gt;By incorporating real-world scenarios into your test automation strategy, you can ensure that your tests are relevant and effective at catching real-world issues. Keep in mind that these advanced techniques are just tools in your testing arsenal — the key is to use them wisely and strategically to achieve your testing goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusive Remarks
&lt;/h2&gt;

&lt;p&gt;In this series of topics, we’ve explored some advanced techniques for Cypress.io test automation, including handling iframes, network stubbing, promise resolving, and custom functions. We’ve provided code examples and explained each concept in detail, and we’ve also highlighted the importance of incorporating real-world scenarios into your testing strategy.&lt;/p&gt;

&lt;p&gt;By mastering these techniques, you’ll be able to write more efficient and effective automated tests, and catch bugs before they make it to production. With Cypress.io’s powerful testing capabilities and your newfound skills, you’ll be able to take your testing game to the next level. Happy testing!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>cypress</category>
    </item>
    <item>
      <title>Mastering Advanced Cypress.io Test Automation [Part 3/4]: Promise Resolving</title>
      <dc:creator>Ahsan Bilal</dc:creator>
      <pubDate>Fri, 12 May 2023 01:37:27 +0000</pubDate>
      <link>https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-34-promise-resolving-4p3b</link>
      <guid>https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-34-promise-resolving-4p3b</guid>
      <description>&lt;p&gt;With the techniques covered in this part, you’ll have a grasp on promise resolution in Cypress.io and be closer to mastering advanced test automation with Cypress. Let’s begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Promise-Resolving
&lt;/h2&gt;

&lt;p&gt;JavaScript is an asynchronous language and often relies on promises to handle async operations. Cypress.io offers powerful tools for handling promises in tests. In this article, we will cover how to resolve promises in Cypress.io tests with an advanced-level example.&lt;/p&gt;

&lt;p&gt;Promise-Resolving with Cypress.io: Promises are a fundamental part of modern JavaScript, and they enable asynchronous operations in a non-blocking manner. In Cypress.io, we can use the &lt;code&gt;.then()&lt;/code&gt; method to resolve promises. However, sometimes we may encounter situations where we need to resolve promises before executing further test cases.&lt;/p&gt;

&lt;p&gt;Consider a scenario where we need to log in to a website and then perform some actions on the dashboard. Cypress.io offers powerful tools for handling such situations.&lt;/p&gt;

&lt;p&gt;Here’s an example code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe('Promise-Resolving', () =&amp;gt; {
  it('Logs in and performs actions on dashboard', () =&amp;gt; {
    cy.visit('https://example.com')
    cy.get('#username').type('testuser')
    cy.get('#password').type('testpassword')
    cy.get('#login-button').click()

    cy.url().then((url) =&amp;gt; {
      if (url.includes('/dashboard')) {
        cy.get('#dashboard-actions').click()
        cy.get('#dashboard-action-1').click()
        cy.get('#dashboard-action-2').click()
      }
      else {
        cy.log('User is not logged in')
      }
    })
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, we first visit the website and enter the login credentials. After clicking on the login button, we resolve the promise by using the &lt;code&gt;.then()&lt;/code&gt; method. We then check if the user is redirected to the dashboard page. If yes, we perform some actions on the dashboard. If not, we log a message saying that the user is not logged in.&lt;/p&gt;

&lt;p&gt;Here is a step-by-step breakdown of the code example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We start by visiting the website using the &lt;code&gt;cy.visit()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;We then use the &lt;code&gt;cy.get()&lt;/code&gt; method to locate the username and password fields and enter the login credentials.&lt;/li&gt;
&lt;li&gt;We click on the login button using the &lt;code&gt;cy.get()&lt;/code&gt; method and the &lt;code&gt;.click()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;After clicking on the login button, we use the &lt;code&gt;cy.url()&lt;/code&gt; method to get the current URL and resolve the promise using the &lt;code&gt;.then()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;We then check if the URL includes ‘/dashboard’. If yes, we perform some actions on the dashboard using the &lt;code&gt;cy.get()&lt;/code&gt; and &lt;code&gt;.click()&lt;/code&gt; methods.&lt;/li&gt;
&lt;li&gt;If the URL does not include ‘/dashboard’, we log a message saying that the user is not logged in.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Complications and Possible Solutions:
&lt;/h3&gt;

&lt;p&gt;One common issue with resolving promises in Cypress.io tests is that it can lead to flaky tests. Flaky tests are tests that sometimes pass and sometimes fail without any obvious reason. This can happen when the promise resolution takes longer than expected, and the test fails because it times out. To avoid flaky tests, we can use the &lt;code&gt;cy.wrap()&lt;/code&gt; method to wrap the promise and ensure that the test waits until the promise is resolved before proceeding.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('Resolves promises using cy.wrap()', () =&amp;gt; {
  // Promise that resolves after 2 seconds
  const promise = new Promise(resolve =&amp;gt; {
    setTimeout(() =&amp;gt; {
      resolve('Promise resolved!')
    }, 2000)
  })

  // Wrapping the promise with cy.wrap() ensures that the test waits for it to resolve
  cy.wrap(promise).should('equal', 'Promise resolved!')
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We define a promise that resolves after 2 seconds using the &lt;code&gt;setTimeout()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;We then wrap the promise with the &lt;code&gt;cy.wrap()&lt;/code&gt; method, which ensures that the test waits for the promise to resolve before proceeding.&lt;/li&gt;
&lt;li&gt;We use the &lt;code&gt;.should()&lt;/code&gt; method to assert that the resolved value of the promise is equal to &lt;em&gt;‘Promise resolved!’&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this way, we can ensure that our tests wait for promises to resolve and avoid flakiness in our Cypress.io tests. But another complication is when we encounter nested promises. In such cases, we can use the &lt;code&gt;Promise.all()&lt;/code&gt; method to resolve multiple promises at once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('Resolves nested promises using Promise.all()', () =&amp;gt; {
  cy.visit('https://example.com')
  cy.get('#my-element').then(element =&amp;gt; {
    // Perform an action that returns a promise
    const promise1 = element.click()
    // Perform another action that returns a promise
    const promise2 = cy.get('#my-other-element').click()
    // Use Promise.all() to wait for both promises to resolve
    Promise.all([promise1, promise2]).then(() =&amp;gt; {
      // Assert that the expected behavior has occurred
      cy.get('#my-element').should('have.class', 'active')
      cy.get('#my-other-element').should('be.visible')
    })
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we’re visiting a website and then selecting an element with the ID &lt;code&gt;#my-element&lt;/code&gt;. We're then performing two actions on this element that return promises: a &lt;code&gt;.click()&lt;/code&gt; action and a &lt;code&gt;cy.get()&lt;/code&gt; action to select another element. We're using &lt;code&gt;Promise.all()&lt;/code&gt; to wait for both of these promises to resolve before asserting that the expected behaviour has occurred.&lt;/p&gt;

&lt;p&gt;Here’s a step-by-step breakdown of what’s happening in this code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We visit the website using &lt;code&gt;cy.visit()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We select an element with the ID &lt;code&gt;#my-element&lt;/code&gt; using &lt;code&gt;cy.get()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We perform an action on this element that returns a promise by calling &lt;code&gt;element.click()&lt;/code&gt;. We store this promise in a variable called &lt;code&gt;promise1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We perform another action that returns a promise by calling &lt;code&gt;cy.get('#my-other-element').click()&lt;/code&gt;. We store this promise in a variable called &lt;code&gt;promise2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We use &lt;code&gt;Promise.all()&lt;/code&gt; to wait for both promises to resolve by passing an array of promises as an argument. When both promises have resolved, the &lt;code&gt;.then()&lt;/code&gt; callback is executed.&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;.then()&lt;/code&gt; callback, we assert that the expected behaviour has occurred by using &lt;code&gt;cy.get()&lt;/code&gt; and &lt;code&gt;.should()&lt;/code&gt; to check that the &lt;code&gt;#my-element&lt;/code&gt; element has the class &lt;code&gt;active&lt;/code&gt; and that the &lt;code&gt;#my-other-element&lt;/code&gt; element is visible.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using &lt;code&gt;Promise.all()&lt;/code&gt; in this way ensures that all promises are resolved before the test continues, helping to prevent flaky tests caused by promise resolution taking longer than expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Handling promises in Cypress.io tests is a critical skill for test automation engineers. It enables us to write more robust tests and handle complex scenarios. In this article, we covered how to resolve promises in Cypress.io tests with an advanced-level example. We also discussed the complications and possible solutions to ensure reliable tests. With these techniques, you can create more robust and efficient tests that can handle complex async scenarios.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you liked this, click ❤ so other people will also notice here.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>testing</category>
      <category>javascript</category>
      <category>e2e</category>
    </item>
    <item>
      <title>Mastering Advanced Cypress.io Test Automation [Part 2/4]: Network Stubbing</title>
      <dc:creator>Ahsan Bilal</dc:creator>
      <pubDate>Fri, 12 May 2023 01:25:10 +0000</pubDate>
      <link>https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-24-network-stubbing-4mgg</link>
      <guid>https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-24-network-stubbing-4mgg</guid>
      <description>&lt;p&gt;With the examples covered in this part, you’ll gain a strong grasp of network stubbing in your Cypress.io test suite and be one step closer to mastering advanced Cypress.io test automation. So, let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Network Stubbing
&lt;/h2&gt;

&lt;p&gt;Another challenge in web application testing is dealing with network requests. In some cases, you may want to simulate network responses in your tests. For example, you might want to test how your application handles errors or slow network connections.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;cy.intercept()&lt;/code&gt; command is used to intercept specific network requests and provide custom responses. You can pass in the HTTP method, URL, and response object as arguments to the &lt;code&gt;cy.intercept()&lt;/code&gt; command. The response object can include a fixture, which is a static JSON file that serves as a mock response.&lt;/p&gt;

&lt;p&gt;Let’s take a look at some code examples to see how network stubbing works in Cypress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1: Simulating a Slow Network Connection
&lt;/h3&gt;

&lt;p&gt;In this example, we’re intercepting a GET request to the URL &lt;code&gt;https://api.example.com/users&lt;/code&gt; and responding with a fixture called “&lt;em&gt;users.json&lt;/em&gt;”. We’re also using the &lt;code&gt;cy.wait()&lt;/code&gt; command to simulate a slow network connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe('Network Stubbing', () =&amp;gt; {
  beforeEach(() =&amp;gt; {
    cy.intercept('GET', 'https://api.example.com/users', {
      fixture: 'users.json'
    }).as('getUsers')
  })

  it('Visits a website that uses an external API', () =&amp;gt; {
    cy.visit('https://www.example.com')
    cy.wait('@getUsers').then(({ response }) =&amp;gt; {
      expect(response.statusCode).to.equal(200)
      expect(response.body).to.have.length(2)
      expect(response.body[0]).to.have.property('name', 'FirstName LastName')
    })
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s break down the code step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;describe&lt;/code&gt; function is used to group related tests together. In this case, we’re grouping tests related to network stubbing.&lt;/li&gt;
&lt;li&gt;The beforeEach function is used to set up a mock server and define a route for the server to respond to using &lt;code&gt;cy.intercept()&lt;/code&gt;. In this case, we’re intercepting a GET request to the URL &lt;code&gt;https://api.example.com/users&lt;/code&gt; and responding with a fixture called “&lt;em&gt;users.json&lt;/em&gt;”.&lt;/li&gt;
&lt;li&gt;The test, &lt;code&gt;it('Visits a website that uses an external API', ()=&amp;gt;{...})&lt;/code&gt;, visits a website and waits for the response from the mocked API route we defined earlier using &lt;code&gt;cy.intercept()&lt;/code&gt;. Once the response is received, we use the &lt;code&gt;.then()&lt;/code&gt; function to perform assertions on the response. In this case, we’re asserting that the response has a status code of 200, has a length of 2, and that the first user object has a name of &lt;em&gt;‘FirstName LastName’&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example 2: Handling Dynamic Responses
&lt;/h3&gt;

&lt;p&gt;In this example, we’re intercepting a dynamic API route and responding with user data. We’re using the &lt;code&gt;.its()&lt;/code&gt; function to drill down into the response JSON and check that the data returned for the user with ID 1 matches our expected data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('Handles dynamic response', () =&amp;gt; {
  // Intercept the dynamic API route and respond with user data
  cy.intercept('GET', '/api/users/*', req =&amp;gt; {
    req.reply({
      statusCode: 200,
      body: {
        id: req.path.split('/')[3],
        name: 'FirstName LastName',
        email: 'fullname@example.com',
        age: 30
      }
    })
  }).as('dynamicApiRoute')
  // Visit a website and wait for response from mocked API route
  cy.visit('/')
  cy.wait('@dynamicApiRoute')
  // Assert that the response contains the correct user data
  cy.get('@dynamicApiRoute')
    .its('response.body')
    .should('deep.equal', {
      id: '1',
      name: 'FirstName LastName',
      email: 'fullname@example.com',
      age: 30
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a step-by-step breakdown of the code example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We start with the test case description: “Handles dynamic response”.&lt;/li&gt;
&lt;li&gt;We then use the &lt;code&gt;cy.intercept()&lt;/code&gt; method to intercept a dynamic API route. The route is defined with a wildcard &lt;code&gt;*&lt;/code&gt; in the URL path, which means that any URL that matches the pattern /&lt;code&gt;api/users/*&lt;/code&gt; will be intercepted.&lt;/li&gt;
&lt;li&gt;Inside the intercept method, we use the &lt;code&gt;req.reply()&lt;/code&gt; method to respond with user data. The req object contains information about the intercepted request, including the URL path. We extract the user ID from the URL path using the &lt;code&gt;.split()&lt;/code&gt; method and add it to the response body.&lt;/li&gt;
&lt;li&gt;We then visit a website using the &lt;code&gt;cy.visit()&lt;/code&gt; method and wait for the response from the mocked API route using the &lt;code&gt;cy.wait()&lt;/code&gt; method. Note that we haven't defined an alias for this route yet.&lt;/li&gt;
&lt;li&gt;We define an alias for the intercepted route using the &lt;code&gt;.as()&lt;/code&gt; method. We use the name &lt;code&gt;dynamicApiRoute&lt;/code&gt; as the alias.&lt;/li&gt;
&lt;li&gt;We then assert that the response contains the correct user data. We use the &lt;code&gt;cy.get('@dynamicApiRoute')&lt;/code&gt; method to get the response for the intercepted route using the alias. We then use the &lt;code&gt;.its()&lt;/code&gt; method to access the response.body property of the response. Finally, we use the &lt;code&gt;.should()&lt;/code&gt; method with the &lt;code&gt;deep.equal&lt;/code&gt; assertion to compare the response body with the expected user data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example 3: Handling Errors
&lt;/h3&gt;

&lt;p&gt;In this example, we’re intercepting an API route that returns a 500 server error using &lt;code&gt;cy.intercept()&lt;/code&gt;. Once again, we’re visiting the website and waiting for the response from the mocked API route. We’re then checking that the response contains the expected error message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('Handles errors', () =&amp;gt; {
  // Intercept an API route that returns a 500 server error
  cy.intercept('GET', '/api/error', {
    statusCode: 500,
    body: 'Internal Server Error'
  }).as('errorRoute')

  // Visit the website and wait for response from mocked API route
  cy.visit('/')
  cy.wait('@errorRoute').then(({ response }) =&amp;gt; {
    expect(response.statusCode).to.equal(500)
    expect(response.body).to.equal('Internal Server Error')
  })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test first intercepts the API route that returns a 500 server error using &lt;code&gt;cy.intercept()&lt;/code&gt;. The method takes three arguments: the HTTP method, the URL to intercept, and an object containing the response to return. In this case, we're returning a response with a status code of 500 and a body of "Internal Server Error". We also give this intercept a unique name using &lt;code&gt;.as('errorRoute')&lt;/code&gt; so that we can reference it later.&lt;/p&gt;

&lt;p&gt;Next, we visit the website using &lt;code&gt;cy.visit()&lt;/code&gt; and wait for the response from the mocked API route using &lt;code&gt;cy.wait('@errorRoute')&lt;/code&gt;. Once the response is returned, we can access it in the callback function using destructuring to get the &lt;code&gt;response&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Finally, we use &lt;code&gt;expect()&lt;/code&gt; to check that the response contains the expected error message. We check the &lt;code&gt;statusCode&lt;/code&gt; property of the response to ensure that it is 500, and we check the &lt;code&gt;body&lt;/code&gt; property of the response to ensure that it matches the expected "Internal Server Error" message.&lt;/p&gt;

&lt;p&gt;By intercepting and mocking API routes in this way, we can simulate different responses from the server and ensure that our frontend code handles them correctly. This makes it easier to test our application and catch errors before they make it to production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Overall, these examples demonstrates how to use network stubbing in Cypress.io to mock API responses and control the data returned by the API. By using network stubbing, we can ensure that our tests are predictable and repeatable, even when testing applications that rely on external APIs.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you liked this, click ❤ so other people will also notice here.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>testing</category>
      <category>javascript</category>
      <category>e2e</category>
    </item>
    <item>
      <title>Mastering Advanced Cypress.io Test Automation [Part 1/4]: Dealing with Iframes</title>
      <dc:creator>Ahsan Bilal</dc:creator>
      <pubDate>Fri, 12 May 2023 01:13:06 +0000</pubDate>
      <link>https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-14-dealing-with-iframes-422m</link>
      <guid>https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-14-dealing-with-iframes-422m</guid>
      <description>&lt;p&gt;Welcome to the first instalment of our series on mastering advanced Cypress.io test automation! In this series, we’ll be diving deep into some of the most complex concepts and techniques for writing efficient and effective automated tests with Cypress.io.&lt;/p&gt;

&lt;p&gt;In this series of articles, we will delve into complex concepts such as handling &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-14-dealing-with-iframes-422m"&gt;&lt;em&gt;iframes&lt;/em&gt;&lt;/a&gt;, &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-24-network-stubbing-4mgg"&gt;&lt;em&gt;network stubbing&lt;/em&gt;&lt;/a&gt;, and &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-34-promise-resolving-4p3b"&gt;&lt;em&gt;resolving promises&lt;/em&gt;&lt;/a&gt; with Cypress.io. Additionally, we will provide you with valuable insights on how to create &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-44-writing-custom-functions-5bkp"&gt;&lt;em&gt;custom functions&lt;/em&gt;&lt;/a&gt; to address the unique testing challenges that Cypress.io does not cover directly. So, fasten your seatbelts and get ready to elevate your Cypress.io proficiency!&lt;/p&gt;

&lt;p&gt;In this first part, we’ll be focusing on one of the most challenging aspects of test automation: dealing with iframes. As you may already know, iframes can present unique challenges for automated testing, since they essentially embed one website inside another. We’ll explore some strategies and techniques for handling iframes in your Cypress.io tests, including how to locate and interact with elements inside iframes, how to assert on iframe content, and how to handle cross-domain iframes.&lt;/p&gt;

&lt;p&gt;By the end of this part, you’ll have a solid understanding of how to tackle iframes in your Cypress.io test suite, and you’ll be well on your way to mastering advanced Cypress.io test automation. So, let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing with Content within Iframes
&lt;/h2&gt;

&lt;p&gt;When testing web applications, it’s not uncommon to come across iframes, which are HTML elements used to embed another document within the current HTML document. Testing content within iframes can be a bit more complicated than testing regular HTML elements, but Cypress.io provides us with the tools we need to tackle this challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example
&lt;/h2&gt;

&lt;p&gt;Suppose you are testing a web page that has a chatbot integrated into an iframe. To test the chatbot functionality, you need to interact with the iframe’s elements. However, because the iframe’s elements are technically part of a separate document, you cannot access them directly from the parent document using the Cypress commands. Instead, you need to switch the context of your test to the iframe document in order to interact with its elements. You can do this by using the &lt;code&gt;cy.get()&lt;/code&gt; command to select the iframe element based on its attributes, using the &lt;code&gt;.then()&lt;/code&gt; method to access the contents of the iframe using the &lt;code&gt;$iframe.contents()&lt;/code&gt; method, and finally, using the &lt;code&gt;cy.wrap()&lt;/code&gt; command to wrap the form element and save it to an alias &lt;code&gt;@form&lt;/code&gt; that you can reference later in your test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Challenge
&lt;/h2&gt;

&lt;p&gt;One of the challenges of testing content within iframes is that the elements within the iframe are technically part of a separate document. This means that we cannot access them directly from the parent document using the Cypress commands. Instead, we need to switch the context of our test to the iframe document in order to interact with its elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code Example
&lt;/h2&gt;

&lt;p&gt;To illustrate how to deal with content within iframes in Cypress.io, let’s use the example of a web page that contains an iframe with a form element. Our goal is to fill out the form and submit it.&lt;/p&gt;

&lt;p&gt;First, we need to identify the iframe element using the &lt;code&gt;cy.get()&lt;/code&gt; command and save it to a variable. We'll use the &lt;code&gt;iframe()&lt;/code&gt; command to get the content of the iframe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.get('iframe[name="my-iframe"]').then(($iframe) =&amp;gt; {
  const iframeContents = $iframe.contents()
  cy.wrap(iframeContents.find('form')).as('form')
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we’re using the &lt;code&gt;cy.get()&lt;/code&gt; command to select the iframe element based on its name attribute. We then use the &lt;code&gt;.then()&lt;/code&gt; method to access the contents of the iframe using the &lt;code&gt;$iframe.contents()&lt;/code&gt; method, which returns the document object of the iframe.&lt;/p&gt;

&lt;p&gt;Next, we use the &lt;code&gt;cy.wrap()&lt;/code&gt; command to wrap the form element and save it to an alias &lt;code&gt;@form&lt;/code&gt; that we can reference later in our test.&lt;/p&gt;

&lt;p&gt;Now that we have access to the iframe document and the form element, we can interact with the form fields and submit the form as we would with any other form element. For example, let’s fill out the form and submit it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.get('@form').find('[name="name"]').type('FirstName LastName')
cy.get('@form').find('[name="email"]').type('firstname.lastname@example.com')
cy.get('@form').find('button[type="submit"]').click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we’re using the &lt;code&gt;cy.get('@form')&lt;/code&gt; command to reference the form element that we saved to the &lt;code&gt;@form&lt;/code&gt; alias earlier. We then use the &lt;code&gt;.find()&lt;/code&gt; method to select the form fields by their name attributes and fill them out using the &lt;code&gt;.type()&lt;/code&gt; command. Finally, we use the &lt;code&gt;.click()&lt;/code&gt; command to submit the form.&lt;/p&gt;




&lt;p&gt;Enough for now.&lt;/p&gt;

&lt;p&gt;In subsequent parts of this article, I’ll talk about &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-24-network-stubbing-4mgg"&gt;Network Interception&lt;/a&gt;, &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-34-promise-resolving-4p3b"&gt;Promise Resolving&lt;/a&gt;, and &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-44-writing-custom-functions-5bkp"&gt;Writing Custom Functions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Up Next: &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-24-network-stubbing-4mgg"&gt;Part 2&lt;/a&gt;, &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-34-promise-resolving-4p3b"&gt;Part 3&lt;/a&gt;, &lt;a href="https://dev.to/ahsanbilal/mastering-advanced-cypressio-test-automation-part-44-writing-custom-functions-5bkp"&gt;Part 4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you liked this, click ❤ so other people will also notice here.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>cypress</category>
      <category>e2e</category>
    </item>
  </channel>
</rss>
