3

How do I conditionally skip a test if the URL contains "xyz"? some tests that run in the QA environment "abc" should not be run in Production "xyz" environment.

I've not been able to find a good example of conditionally checking for environment to trigger a test. The baseURL needs to be checked dynamically and the test skipped preferably in the beforeEach.

running cypress 6.2.0

beforeEach(() => {
    login.loginByUser('TomJones');
    cy.visit(`${environment.getBaseUrl()}${route}`);
 });

it('test page', function () {
     if environment.getBaseUrl().contains("xyz")
       then *skip test* 
     else
       cy.intercept('GET', '**/some-api/v1/test*').as('Test'););     
       cy.get('#submitButton').click();
})

Potential Solution (tested and tried successfully): I used a combination of filtering (grouping) and folder structures via CLI I set folders /integrations/smokeTest/QA and /integrations/smokeTest/Prod/

1.QA Test Run: 
  npm run *cy:filter:qa* --spec "cypresss/integration/smokeTests/QA/*-spec.ts"

2.Run All (both QA and PROD tests)
  npm run cypress:open --spec "cypresss/integration/smokeTests/*/*-spec.ts"

3. Prod Test Run: 
npm run cy:filter:prod --spec "cypresss/integration/smokeTests/PROD*/*-spec.ts"



Dominique M.
  • 31
  • 1
  • 3
  • 2
    Similar problem to [How to add test case grouping in Cypress](https://stackoverflow.com/a/65045605/12697177) –  Dec 30 '20 at 10:18
  • Conditional testing is not recommended (https://docs.cypress.io/guides/core-concepts/conditional-testing.html#Definition). I would create a separate test suits for different environments, or user tags to tag certain tests. – Jonah Dec 30 '20 at 14:19
  • Thank your for the guidance, I will review both approaches. There are so many tests that in QA WIP for a domain in the test repo. I typically have tests for the domain in one repo and just run them against all environments. obviously the QA tests run and will fail in the Prod domains.. Thank you again.. I will check these out and see which requires the least amount of effort to switch a test run from QA to PROD when deployed to prod. Cheers. – Dominique M. Dec 30 '20 at 21:12
  • @MarionMorrison I tested combination of filtering (grouping) and folder structures. thank you. – Dominique M. Dec 31 '20 at 09:22

2 Answers2

5

Normally I wouldn't write a custom command just to exercise one Cypress command, but in this case it's useful to obtain the global test context this.

Using the function form of callback with the custom command allows access to this, then you are free to use arrow functions on the test themselves.

Cypress.Commands.add('skipWhen', function (expression) {
  if (expression) {
    this.skip()
  }
})

it('test skipping with arrow function', () => {

  cy.skipWhen(Cypress.config('baseUrl').includes('localhost'));

  // NOTE: a "naked" expect() will not be skipped
  // if you call your custom command within the test
  // Wrap it in a .then() to make sure it executes on the command queue

  cy.then(() => {
    expect('this.stackOverflow.answer').to.eq('a.better.example')
  })
})
Schiff
  • 165
  • 1
  • 7
1

I would add a helper method which you can call from any Mocha.Context (at the time of writing, any it, describe, or context block).

// commands.ts
declare global {
  // eslint-disable-next-line @typescript-eslint/no-namespace
  namespace Cypress {
    interface Chainable {
      /**
       * Custom command which will skip a test or context based on a boolean expression.
       *
       * You can call this command from anywhere, just make sure to pass in the the it, describe, or context block you wish to skip.
       *
       * @example cy.skipIf(yourCondition, this);
       */
      skipIf(expression: boolean, context: Mocha.Context): void;
    }
  }
}

Cypress.Commands.add(
  'skipIf',
  (expression: boolean, context: Mocha.Context) => {
    if (expression) context.skip.bind(context)();
  }
);

And from your spec:

describe('Events', () => {
  const url = `${environment.getBaseUrl()}${route}`;

  before(function () {
    cy.visit(url);
    cy.skipIf(url.includes('xyz'), this);
  });

  context('Nested context', () => {
    it('test', function () {
      cy.skipIf(url.includes('abc'), this);
      expect(this.stackOverflow.answer).to.be('accepted');
    });
  });
});

Now you have a reusable custom command that you can call from anywhere to conditionally skip tests based on any expression that evaluates to a boolean. Careful of classic JS equality and definition gotchas (read more about equality in JS here).

GrayedFox
  • 2,350
  • 26
  • 44