skip to Main Content

I’m writing an automation which basically reads the list of urls from an excel sheet and check the status of each url whether it’s success(200), redirected(301/302) or Not Found(404) and based on the response I’m updating the sheet with the status against each url.

I’m able to cover almost all conditions but struggling with the urls whose domain is either not accessible or non reachable, because it’s a network error so whenever my code tries to access those urls the test is getting terminated at that particular stage and the whole automation fails. Instead that I want to skip those urls and update the sheet with the status Non reachable or something like that.

I’m not able to find a correct way to cover this case I tried all my best as a beginner in cypress.

Here I’m adding what I tried.

const XLSX = require('xlsx');

describe('Website Test', () => {
it('should open websites from Excel and update status', () => {
// Read Excel file
cy.readFile('/Link.xlsx', 'binary').then((fileContent) => {
  const workbook = XLSX.read(fileContent, { type: 'binary' });
  const sheetName = workbook.SheetNames[0];
  const worksheet = workbook.Sheets[sheetName];

  // Get all URLs from the Excel sheet
  const urls = XLSX.utils.sheet_to_json(worksheet, { header: 1, range: 1 });

  // Iterate through each URL
  urls.forEach((url, rowIndex) => {
    const websiteUrl = url[1]; // Assuming the URL is in the first column

    // Check if the websiteUrl is empty, and terminate the test if true
    if (!websiteUrl) {
      cy.log(`Skipping empty row at index ${rowIndex}`);
      return;
    }
    
    // Use cy.request to get the response status, follow redirects
    cy.request({
      url: websiteUrl,
      followRedirect: false,
      failOnStatusCode: false,
    }).then((response) => {
      // Update status in Excel based on the final status
      let status;
      let result;
      if (response.status === 302 || response.status === 301) {
        status = `redirected to ${response.redirectedToUrl}`;
      } else if (response.status === 200) {
        status = 'opened';
      } else {
        status = 'failed';
      }

      XLSX.utils.sheet_add_aoa(worksheet, [[status]], { origin: `C${rowIndex + 2}` });
      XLSX.utils.sheet_add_aoa(worksheet, [[result]], { origin: `D${rowIndex + 2}` });

      // Save the updated Excel file after each request
      const updatedFileContent = XLSX.write(workbook, { bookType: 'xlsx', type: 'binary' });
      cy.writeFile('Link.xlsx', updatedFileContent, 'binary');
    });
  });
});

With this approach test is failing at cy.request() for non accessible domains with an error message: Error: getaddrinfo ENOTFOUND bvicameroon.com

I tried one more approach using cy.intercept().

    cy.intercept('GET', websiteUrl, (req) => {
      console.log(req)
      req.continue((res) => {
        console.log(res)
      })
    }).as('websiteUrlRequest');

    cy.wait('@websiteUrlRequest', { timeout: 10000 }).then((interception) => {
      console.log(interception)
    });

With this approach first of all I’m not able to log the req/res of intercept. It is logging interception object inside cy.wait but only for valid domains It’s failing on cy.wait() for non accessible domains with error message:

CypressError
Timed out retrying after 10000ms: cy.wait() timed out
waiting 10000ms for the 1st request to the route: websiteUrlRequest. No
request ever occurred

Can anyone suggest me the possible approach to do cover the condition for non accessible domains (Network Error)?

2

Answers


  1. The way to check that a URL is reachable is with ping.
    This answer is relevant to your issue Checking if host is online in Cypress.

    Broadly, you do that check prior to cy.request(), same as empty URL check but it’s an asynchronous call so it will check inside the .then() callback.

    // Check if the websiteUrl is empty
    if (!websiteUrl) {
      cy.log(`Skipping empty row at index ${rowIndex}`);
      return;
    }
    
    // Check if the websiteUrl is reachable
    const host = websiteUrl.replace('https://', '')  // only host part for ping
    cy.exec(`ping ${host}`, {failOnNonZeroExit: false}).then(reply => {
      if (reply.code !== 0) {
        cy.log(`Skipping unreachable URL at index ${rowIndex}`);
        return;
      } else {
        cy.request({
          ...
    

    If you extract the code to update XL to a function, you can also update after ping failure.

    function updateXL({status, result}) {
      XLSX.utils.sheet_add_aoa(worksheet, [[status]], { origin: `C${rowIndex + 2}` });
      XLSX.utils.sheet_add_aoa(worksheet, [[result]], { origin: `D${rowIndex + 2}` });
    
      // Save the updated Excel file after each request
      const updatedFileContent = XLSX.write(workbook, { bookType: 'xlsx', type: 'binary' });
      cy.writeFile('Link.xlsx', updatedFileContent, 'binary');
    }
    
    ...
    
    // Check if the websiteUrl is reachable
    const host = websiteUrl.replace('https://', '')  // only host part for ping
    cy.exec(`ping ${host}`, {failOnNonZeroExit: false}).then(reply => {
      if (reply.code !== 0) {
        cy.log(`Skipping unreachable URL at index ${rowIndex}`);
        updateXL({status: 'unknown', result: 'unreachable'})
        return;
      } else {
        cy.request({
          ...
    

    Simple examples:

    cy.exec('ping google.com', {failOnNonZeroExit: false}).then(reply => {
      expect(reply.code).to.eq(0)   // success
      expect(reply.stdout.startsWith('Pinging google.com')).to.eq(true)
    })
    
    cy.exec('ping bvicameroon.com', {failOnNonZeroExit: false}).then(reply => {
      expect(reply.code).to.eq(1)   // failed
      expect(reply.stdout.startsWith('Ping request could not find host bvicameroon.com')).to.eq(true)
    })
    

    enter image description here

    Login or Signup to reply.
  2. For anyone having trouble calling ping from the cy.exe() command, maybe because the OS is incompatable, an alternative is to use the node-ping package and call it via a cy.task() command.

    First install the ping package

    yarn add ping
    

    Then add the task command to cypress.config.js

    const { defineConfig } = require("cypress");
    const ping = require('ping')
    
    module.exports = defineConfig({
      e2e: {
        setupNodeEvents(on, config) {
          on('task', {
            ping(host) {
              return new Promise((resolve) => {
                ping.sys.probe(host, (isAlive) => resolve(isAlive))
              })
            },
          })
        },
      },
    })
    

    Then in the test, use the true/false return value as required

    cy.task('ping', 'google.com').then(isAlive => {
      expect(isAlive).to.eq(true)
    })
    
    cy.task('ping', 'bvicameroon.com').then(isAlive => {
      expect(isAlive).to.eq(false)
      // or
      if (isAlive) {
        ...
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search