Simulating Internet Outage and Recovery using Cypress
Tags: testing, cypress, webdev, javascript
Published: 2024-01-26 00:57:52

## Unveiling Cypress's Power: Testing Internet Outages and Recoveries with Precision

Testing an application under various scenarios is crucial to ensure its robustness and user-friendliness.

One common yet challenging scenario is simulating internet outages and recoveries.

In this blog post, we'll explore a [Cypress](https://cypress.io/) test that replicates this scenario, utilizing the powerful [`intercept`](https://on.cypress.io/intercept) command to manipulate network requests and responses.

> This blog post was originated by the following [test](https://github.com/wlsf82/cypress-playground/blob/main/cypress/e2e/playground.cy.js#L149C3-L175C5), from the [Cypress Playground](https://github.com/wlsf82/cypress-playground) repository.

### The Test Scenario

The test aims to simulate the internet going "down" and then recovering.

Let's walk through the code step by step to understand how it achieves this:

```js
// Complete Code

it('simulates the internet going "down" then back "up"', () => {
  // Simulating Network Error
  cy.intercept(
    'GET',
    'https://jsonplaceholder.typicode.com/todos/1',
    { forceNetworkError: true }
  ).as('networkError')

  // Triggering the Request
  cy.contains('button', 'Get TODO').click()

  // Handling the Network Error
  cy.wait('@networkError')
  cy.contains(
    '.error span',
    'Oops, something went wrong. Check your internet connection, refresh the page, and try again.'
  ).should('be.visible')

  // Triggering Recovery
  cy.reload()

  // Simulating Successful Request
  cy.intercept(
    'GET',
    'https://jsonplaceholder.typicode.com/todos/1',
    { middleware: true }
  ).as('getTodo')

  cy.contains('button', 'Get TODO').click()

  cy.wait('@getTodo')
    .its('response.statusCode')
    .should('be.equal', 200)

  // Validating Result
  cy.contains('ul li', 'TODO ID: ').should('be.visible')
  cy.contains('ul li', 'Title: ').should('be.visible')
  cy.contains('ul li', 'Completed: ').should('be.visible')
  cy.contains('ul li', 'User ID: ').should('be.visible')
})
```

### Breaking It Down

Let's break it down, so you can understand each piece of code step-by-step.

#### 1. Simulating Network Error

```js
cy.intercept(
  'GET',
  'https://jsonplaceholder.typicode.com/todos/1',
  { forceNetworkError: true }
).as('networkError')
```

In this section, we use the `cy.intercept` command to intercept any GET request to the specified URL (`https://jsonplaceholder.typicode.com/todos/1`). The interception is configured to force a network error (`forceNetworkError: true`). The interception is named 'networkError' using the `as` command, allowing us to wait for it later.

#### 2. Triggering the Request

```js
cy.contains('button', 'Get TODO').click()
```

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.'

#### 3. Handling the Network Error

```js
cy.wait('@networkError')
```

The `cy.wait('@networkError')` 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.

```js
cy.contains(
  '.error span',
  'Oops, something went wrong. Check your internet connection, refresh the page, and try again.'
).should('be.visible')
```

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.

#### 4. Triggering Recovery

```js
cy.reload()
```

This line reloads the page, simulating a user's attempt to recover from the network error.

#### 5. Simulating Successful Request

```js
cy.intercept(
  'GET',
  'https://jsonplaceholder.typicode.com/todos/1',
  { middleware: true }
).as('getTodo')
```

Here, we intercept the same GET request, but this time, we simulate a successful response (`{ middleware: true }`). The interception is named 'getTodo'.

> For more details about the `middleware` property, I recommend reading about the [interception lifecycle](https://docs.cypress.io/api/commands/intercept#Interception-lifecycle), directly from the Cypress official docs.

```js
cy.contains('button', 'Get TODO').click()
```

Another user action triggers the successful request interception.

```js
cy.wait('@getTodo')
  .its('response.statusCode')
  .should('be.equal', 200)
```

The test waits for the 'getTodo' interception and asserts that the response status code is 200, confirming the successful recovery.

#### 6. Validating Result

The subsequent lines validate the presence of specific elements on the page, ensuring that the application displays the expected data after the recovery.

```js
cy.contains('ul li', 'TODO ID: ').should('be.visible')
cy.contains('ul li', 'Title: ').should('be.visible')
cy.contains('ul li', 'Completed: ').should('be.visible')
cy.contains('ul li', 'User ID: ').should('be.visible')
```

These assertions check for the visibility of elements indicating that the application has successfully fetched and displayed the TODO details.

### Conclusion

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.

Realistic scenarios, powered by Cypress commands like `intercept`, enable effective validation of application behavior under challenging conditions.

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

___

Did you like the content? Leave a comment.

___

Would you like to learn Cypress in a hands-on course?

I introduce you to my newest course, [🌲 Cypress, from Zero to the Cloud ☁️](https://www.udemy.com/course/cypress-from-zero-to-the-cloud/?referralCode=CABCDDFA5ADBB7BE2E1A).

I hope you like it, and happy testing!