Search code examples
cypresscypress-configuration

Make Cypress-tests with a config file, so the port of the baseUrl can be overridden in each test (maybe as an env-variable)


I have a cypress.config.ts-file looking like this:

import {defineConfig} from "cypress";

export default defineConfig(
    {
        e2e: {
            baseUrl: 'http://localhost:3000',
        }
    }
    ...
    ...

Problem 1: The application I'm building has to use different ports for different features. Example:

Problem 2: Cypress automatically adds trailing slash to baseUrl, so I can't add the port myself later (inside the individual test), without making some string-manipulation-gymnastics.

So how do I set this up, so I, in the beginning of a test, can define which port should be used? Such as this:

// This doesn't work: 

it('Test feature 1', () => {
    Cypress.env('PORT', 3000);
    cy.request('GET', 'feature-1').as('featureOne')
    ...
    ...
});

it('Test feature 2', () => {
    Cypress.env('PORT', 3002);
    cy.request('GET', 'feature-2').as('featureTwo')
    ...
    ...
});

Solution attempt 1: Leave baseUrl as an empty string

If I let me cypress.config.ts be like this:

import {defineConfig} from "cypress";

export default defineConfig(
    {
        e2e: {
            baseUrl: '',
        }
    }
    ...

Then I can reference the URL fully like this:

it('Test feature 1', () => {
    Cypress.env('PORT', 3000);
    cy.request('GET', 'http://localhost:3000/feature-1').as('featureOne')
    ...
    ...
});

it('Test feature 2', () => {
    Cypress.env('PORT', 3002);
    cy.request('GET', 'http://localhost:3002/feature-2').as('featureTwo')
    ...
    ...
});

It works. But it seems silly.


Solution attempt 2: Fiddle around with cypress.config.ts

I imagined being able to do something like this:

const PORT = process.env.PORT || 3000

export default defineConfig(
    {
        e2e: {
            baseUrl: 'http://localhost' + PORT, 
        }
    }
    ...
    ...

This works, but I'm unable to override the PORT inside of the tests (Cypress.env('PORT', 3002);). I don't know if it's because it runs too late.

So in total, this doesn't work. But it would be smart if it did. :-)


Solution

  • The switch command is a bit old-fashioned, it is generally considered better to use a mapping object.

    If you want to start with something like this in your test

    it('tests with staging url', () => {
      cy.setBaseUrl('staging')
      // test code here
    })
    

    then the custom command setBaseUrl could look like this

    Cypress.Commands.add('setBaseUrl', 
      {prevSubject:false}, 
      (key = 'default') => {
        const baseUrl = Cypress.config('baseUrl') || 'http://localhost:3000/'
        const host = baseUrl.split(':').slice(0,2).join(':')
    
       const portMapping = {
          'default': 3000,
          'staging': 3001,
          'production': 3002,
          ...Cypress.env('ports')
        }
        const port = portMapping[key]
        if (!port) {
          throw new Error (`Incorrect port, should be one of "${Object.keys(portMapping).join(', ')}"`)
        }
    
        const newBaseUrl = `${host}:${port}/`
        return Cypress.config('baseUrl', newBaseUrl)
      }
    )
    
    • baseUrl can be set in cypress.config.js, if not it is 'http://localhost:3000/'
    • default port is 3000
    • if you ask for an unknown port in the test, an error is thrown

    Example tests

    it('tests with default url', () => {
      cy.setBaseUrl()
        .should('eq', 'http://localhost:3000/')
    })
    
    it('tests with staging url', () => {
      cy.setBaseUrl('staging')
        .should('eq', 'http://localhost:3001/')
    })
    
    it('tests with production url', () => {
      cy.setBaseUrl('production')
        .should('eq', 'http://localhost:3002/')
    })
    
    it('tests with unknown url', () => {
      cy.setBaseUrl('mistake')
        .should('eq', 'http://localhost:3002/')
    })
    

    Example overwriting ports at the command line

    yarn cypress open --env ports={\"staging\":4001,\"production\":4002}