Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cypress runs commands twice when no baseUrl defined #2777

Open
rafael-anachoreta opened this issue Nov 14, 2018 · 32 comments
Open

Cypress runs commands twice when no baseUrl defined #2777

rafael-anachoreta opened this issue Nov 14, 2018 · 32 comments
Labels
E2E Issue related to end-to-end testing existing workaround prevent-stale mark an issue so it is ignored by stale[bot] Triaged Issue has been routed to backlog. This is not a commitment to have it prioritized by the team. type: bug

Comments

@rafael-anachoreta
Copy link

Current behavior:

Right now, whenever you start Cypress it will kick off some of the commands twice.

This isn't a problem most of the time as tests should be self contained anyway, but if you are using before hooks (for instance, to login and store cookies, as suggested by the docs) it becomes quite detrimental.

Desired behavior:

Cypress should only run once.

Steps to reproduce:

//__bug.spec.js
describe('Bug?', ()=>{
    before(() =>{
        cy.task('message', 'I\'m running!');
    });

    it('Should only log once', () => {
        cy.visit('https://www.google.com');
    });
});

//index.js
module.exports = (on) => {
    on('task', {
        message (args) {
            console.log(args);

            return null;
        }
    });
};
  • Run the spec
  • Results:
====================================================================================================

  (Run Starting)

  ┌────────────────────────────────────────────────────────────────────────────────────────────────┐
  │ Cypress:    3.1.1                                                                              │
  │ Browser:    Electron 59 (headless)                                                             │
  │ Specs:      1 found (__bug.spec.js)                                                            │
  │ Searched:   cypress/integration/__bug.spec.js                                                  │
  └────────────────────────────────────────────────────────────────────────────────────────────────┘


────────────────────────────────────────────────────────────────────────────────────────────────────

  Running: __bug.spec.js...                                                                (1 of 1)


  Bug
I'm running!
I'm running!
    ✓ Should only log once (1159ms)

Note: this isn't exclusive to hooks! The below spec will also print unwanted results:

describe('Bug', ()=>{

    it('Should only log once', () => {
        cy.task('message', 'I\'m running!');
        cy.visit('https://www.google.com');
    });
    it('Should only log once', () => {
        cy.task('message', 'I\'m running!');
        cy.visit('https://www.google.com');
    });
    it('Should only log once', () => {
        cy.task('message', 'I\'m running!');
        cy.visit('https://www.google.com');
    });
    it('Should only log once', () => {
        cy.task('message', 'I\'m running!');
        cy.visit('https://www.google.com');
    });

});

Results:

Running: __bug.spec.js...                                                                (1 of 1)


  Bug
I'm running!
I'm running!
    ✓ Should only log once (1091ms)
I'm running!
    ✓ Should only log once (3876ms)
I'm running!
    ✓ Should only log once (992ms)
I'm running!
    ✓ Should only log once (1449ms)

If the commands are inverted (i.e., if you visit() before logging) then the results are fine, so maybe Cypress waits for visit then reboots?

Versions

Electron 59 headless
Cypress 3.1.1
macOS High Sierra 10.13.6

@rafael-anachoreta rafael-anachoreta changed the title Cypress starts and run commands twice Cypress starts and runs commands twice Nov 14, 2018
@jennifer-shehane jennifer-shehane added the stage: needs investigating Someone from Cypress needs to look at this label Nov 14, 2018
@dawidkostyszak
Copy link

I found that this happened when you visit url which is different to baseUrl in config.

@dirtyhenry
Copy link

I met the same bug.

In my case, it's worth noting that before code runs twice only when all specs are run at once (ie click on Run all specs). When run one by one, each spec behaves as expected.

@jennifer-shehane
Copy link
Member

@dirtyhenry Any code provided within the support file will run before each spec file as documented here: https://on.cypress.io/writing-and-organizing-tests#Support-file

@jennifer-shehane
Copy link
Member

Hey @rafael-anachoreta, thank you for providing this great detail on this issue.

I have confirmed that indeed, these cy.task() commands are running twice, which is unintended behavior. I've also confirmed that this bug is only present when baseUrl is not defined.

I imagine this has to do with how we handle visiting sites when no baseUrl is defined. See an explanation of this behavior here.

Workaround Today Provide a baseUrl within your Cypress configuration

@jennifer-shehane jennifer-shehane added stage: ready for work The issue is reproducible and in scope difficulty: 2️⃣ type: bug and removed stage: needs investigating Someone from Cypress needs to look at this labels Jan 15, 2019
@jennifer-shehane jennifer-shehane changed the title Cypress starts and runs commands twice Cypress runs commands twice when no baseUrl defined Jan 15, 2019
@dirtyhenry
Copy link

dirtyhenry commented Jan 17, 2019

Hi @jennifer-shehane: I don't really understand your message since none of my code is in the support file.

@dawidkostyszak
Copy link

dawidkostyszak commented Jan 17, 2019

@jennifer-shehane same behaviour is when baseUrl is defined but I want to visit other page. Ie. I set baseUrl='https://www.google.com/' and in my test will do cy.visit('https://duckduckgo.com/') then all before commands will run twice.

@jennifer-shehane
Copy link
Member

@dirtyhenry Sorry for not being clear. If you want code to run only once before each spec file as opposed to before each test, make sure to place the before hook within your support file.

@rblmdst
Copy link

rblmdst commented Mar 9, 2019

Hello everyone,
Any update ? In my case I am using cy.task() to load/unload data in database using the before/after hooks, so it is causing unexpected behavior.

@ollie-o
Copy link

ollie-o commented May 7, 2019

@jennifer-shehane Do you know of any workarounds other than setting baseUrl?

@luliandro
Copy link

luliandro commented Jan 31, 2020

I have the same issue even when baseUrl is set to http://localhost:3000.

I'm using this hack to avoid running the commands twice

in the cypress.json file I have

"firstRun": true

and in the in support index.js:

beforeEach(function() {
  if (Cypress.config("firstRun")) {
    cy.exec("your command");
    Cypress.config("firstRun", false);
  }
});

afterEach(function() {
  Cypress.config("firstRun", true);
});

@jamesalexmorgan
Copy link

Totes looking forward to this fix! 😱🙊

Tried the Cypress.config("firstRun") workaround and baseUrl in config but still executes twice 😭

@eduardosousaufjf
Copy link

@jamesalexmorgan same here. still an issue for me. any workaround?

@nastyanahrebna
Copy link

Have the same issue and can't set baseUrl because tests running in several environments.
My workaround is setting baseURL in plugin file.

plugins/index.js

module.exports = (on, config) => {

  const env = config.env.environment;
  const url = config.env[env].url;

  config.baseUrl = url;

  return config
}

cypress.env.json

 "env1": {
    "url": "https://url.env1.com"
  },
  "env2": {
    "url": "https://url.env2.com"
  }

and runing commands

npx cypress run --env environment=env1
npx cypress open --env environment=env2

@JakubKubista
Copy link

Have the same issue and can't set baseUrl because tests running in several environments.
My workaround is setting baseURL in plugin file.

plugins/index.js

module.exports = (on, config) => {

  const env = config.env.environment;
  const url = config.env[env].url;

  config.baseUrl = url;

  return config
}

cypress.env.json

 "env1": {
    "url": "https://url.env1.com"
  },
  "env2": {
    "url": "https://url.env2.com"
  }

and runing commands

npx cypress run --env environment=env1
npx cypress open --env environment=env2

Good job, thanks! 👍

@sherlaimov-osdb
Copy link

sherlaimov-osdb commented Aug 31, 2020

I'm doing a full-cycle registration test in which a confirmation email is sent, then a task is triggered to open the email and find a confirmation link (with a domain different from the one set in baseUrl) in the inbox. Once the link is found, cy.visit(confirmationLink) results in the test being run twice.

Really hope to see a feasible workaround for this.

@kfenske
Copy link

kfenske commented Sep 24, 2020

@jennifer-shehane I see that you have labeled this as the intended workaround. However, have you seen occasions where this workaround does not work? It seems like I am not the only one who is unable to get this duplicate behavior to stop even when setting a baseUrl in the cypress.json file

@jermoef
Copy link

jermoef commented Sep 25, 2020

Had the same issue and realized it was because my beforeEach was an async function

@Urszulasu
Copy link

Urszulasu commented Oct 16, 2020

I'm doing a full-cycle registration test in which a confirmation email is sent, then a task is triggered to open the email and find a confirmation link (with a domain different from the one set in baseUrl) in the inbox. Once the link is found, cy.visit(confirmationLink) results in the test being run twice.

Really hope to see a feasible workaround for this.

@jennifer-shehane have You any idea how this could work? I have this same issue.
And next case - i have this same problem in CI, when tests are running in pipeline.

rcowsill added a commit to rcowsill/NodeGoat that referenced this issue Nov 8, 2020
* Set config.baseUrl and visit relative URLs to avoid Cypress bug which
  runs "before" hooks twice (github.com/cypress-io/cypress/issues/2777)
* Remove "after" hook dbResets - make tests responsibile for their own
  initial state, not that of the subsequent test
@jennifer-shehane
Copy link
Member

jennifer-shehane commented Jan 8, 2021

Another example of this behavior is with people who set the baseUrl dynamically. Mentioned in this issue: #3454

Having no baseUrl set in cypress.json, this code runs the task twice.

it('Should only log once', () => {
  cy.task('log', 'running!')
  Cypress.config('baseUrl', 'https://docs.cypress.io')
  cy.visit('/')
})

Screen Shot 2021-01-08 at 10 50 16 AM

A more realistic example is someone dynamically generating this url

Cypress.config('baseUrl', `https://${getOrigin()}.cypress.io`)

This is currently the best workaround in this situation I believe: #2777 (comment)

rcowsill added a commit to rcowsill/NodeGoat that referenced this issue Jan 15, 2021
* Set config.baseUrl and visit relative URLs to avoid Cypress bug which
  runs "before" hooks twice (github.com/cypress-io/cypress/issues/2777)
* Remove "after" hook dbResets; make tests responsible for their own
  initial state, not that of the subsequent test
@dwhyteSA
Copy link

dwhyteSA commented Feb 16, 2022

I have the same issue however, I am using a before statement with a request statement to an api with a cypress custom command to create a user then beforeEach test case logs that newly created user in on the website that I'm building scripts on cypress for. So when this is running it creates two new users every time, sometimes it logs in the first user.
before(()=> cy.createAccount()); beforeEach(()=>cy.login()); it("test case"()=> cy.get("button").click(); )
I have the below for the config on support/index.js
module.exports = (on, config) => { const url = config.env["api"].url; config.baseUrl = url; return config; }
Where the config.env.json
{ "api":"url used in api create user" }
What's the eta on this to be completed? Otherwise, the database holding the users will be full in no time!

@brian-mann
Copy link
Member

This is expected behavior based on the way we switch the top superdomain. We could forcibly restrict the before from running when the top domain switches, but avoiding it would result in different breaking and unexpected behavior.

@dwhyteSA
Copy link

Thanks for getting back to me @brian-mann , Do you have any suggestions for this not to run basically twice?

@owen-lopez
Copy link

owen-lopez commented Mar 23, 2022

I have my baseUrl set in my cypress.json and it still runs twice.
For me, this is definitely specific to logic running cy.visit("different url from baseUrl") within a custom Command. It doesn't run everything twice, just the test case that calls the custom Command that invokes the cy.visit.

@qzmenko
Copy link

qzmenko commented Apr 14, 2022

I'm doing a full-cycle registration test in which a confirmation email is sent, then a task is triggered to open the email and find a confirmation link (with a domain different from the one set in baseUrl) in the inbox. Once the link is found, cy.visit(confirmationLink) results in the test being run twice.
Really hope to see a feasible workaround for this.

@jennifer-shehane have You any idea how this could work? I have this same issue. And next case - i have this same problem in CI, when tests are running in pipeline.

I have not found a better solution than to make the fake first visit so that cypress understands which domain he needs to visit and so that he does not make visit twice to confirmation URL.

it('Confirm email', () => {
    cy.task('loadData').then((userData) => {
      // HACK: This visit is required.
      // Сypress has a bug/feature that after changing the domain
      // (in our case from yopmail in previous test to baseUrl in this test),
      // it goes to the url specified in the first visit twice.
      // This usually does not cause problems, but since we have an email confirmation URL,
      // we cannot click on this link twice.
      cy.visit('/');

      cy.visit(userData.confirmUrl);
      cy.contains('You have just used your one-time login link. Your account is now active and you are authenticated.');
    })
  })

@groom7
Copy link

groom7 commented Jun 1, 2023

Disabling the following setting in the cypress.config.ts helped me: testIsolation: false

@nagash77 nagash77 added E2E Issue related to end-to-end testing Triaged Issue has been routed to backlog. This is not a commitment to have it prioritized by the team. and removed stage: icebox labels Jun 1, 2023
@mryellow
Copy link

mryellow commented Jun 12, 2023

Based on suggestions of using plugin file...

Adding the baseUrl adjustment to setupNodeEvents didn't help. setupNodeEvents itself is being ran twice (When ran via Github Actions).

@JoannaG33
Copy link

In the local development environment, I found that this double execution of a cy.request to a test data endpoint only occured when running Cypress in the CLI. With the GUI it runs just once. I managed to fix this by setting a baseUrl with its value being the same as our test data endpoint. However, the same trick will not work when running Cypress in GitLab. It's still executed twice there.

It's kind of crazy that this has been an issue since 2018.

@piotrpalek
Copy link

piotrpalek commented Oct 5, 2023

I believe I have encountered the same bug when running component tests, is the baseUrl workaround also recommended then? In my case I have set retries: { runMode: 1, , which sometimes causes cypress to run two attempts at once (very flaky behavior):

image

@riva-amcfarlane
Copy link

Based on suggestions of using plugin file...

Adding the baseUrl adjustment to setupNodeEvents didn't help. setupNodeEvents itself is being ran twice (When ran via Github Actions).

I'm also encountering this issue. I have baseURL is set in cypress config, and tests are being executed twice in GitHub Actions.

@ChaonengQuan
Copy link

Also encountering the same issue, commenting to increase visibility

@mankittens
Copy link

Currently working on this bug at my company. If we can't find a workaround, we're switching to Playwright.

skazy737 pushed a commit to skazy737/DevOPS that referenced this issue Oct 11, 2024
* Set config.baseUrl and visit relative URLs to avoid Cypress bug which
  runs "before" hooks twice (github.com/cypress-io/cypress/issues/2777)
* Remove "after" hook dbResets; make tests responsible for their own
  initial state, not that of the subsequent test
@jennifer-shehane
Copy link
Member

A related issue where the retries states are duplicated in the after:run hook due to this bug also. #30794

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E2E Issue related to end-to-end testing existing workaround prevent-stale mark an issue so it is ignored by stale[bot] Triaged Issue has been routed to backlog. This is not a commitment to have it prioritized by the team. type: bug
Projects
None yet
Development

No branches or pull requests