javascriptnode.jsautomated-testscypress

Cypress can't seem to get the URL value after removing target attribute, despite the page loading fine


I want Cypress to check that the link to a page is correct by clicking that links and seeing if the URL contains a certain string.

For that, I've created the function:

checkLink = (linkEl, expectedPath) => {
    let pathString = linkEl.prop('href') ? linkEl.prop('href') : 'no-href';
    if (expectedPath && (pathString != 'no-href')) {
        cy.task('log', 'Checking link: '  + pathString + ' ' + expectedPath);
        cy.get(linkEl).click();
        cy.url().should('include', expectedPath);
        cy.go('back');
    }
}

For most cases this worked fine.

However, it would not work if the link had a target="_blank" attribute. So I added .invoke('removeAttr', 'target') and changed the function to be the following:

checkLink = (linkEl, expectedPath) => {
    let pathString = linkEl.prop('href') ? linkEl.prop('href') : 'no-href';
    if (expectedPath && (pathString != 'no-href')) {
        cy.task('log', 'Checking link: '  + pathString + ' ' + expectedPath);
        cy.get(linkEl).invoke('removeAttr', 'target').click();
        cy.url().should('include', expectedPath);
        cy.go('back');
    }
}

However, now it can't seem to get the URL of the page it visits. Eg I get the error:

 AssertionError: Timed out retrying after 4000ms: expected '' to include 'mystring'

If I run the test as headed I can see the page (with the expected string in the URL) load fine. It just seem that Cypress is getting nothing from cy.url() anymore for some reason.

Would anyone know why this is at all?


Solution

  • Cypress does not support visiting multiple pages in one test. To check the URL of the link after clicking you must do so inside a cy.origin() command.

    const checkLink = (linkEl, expectedPath) => {
      if (!expectedPath || !linkEl.attr('href')) return
    
      cy.wrap(linkEl).invoke('removeAttr', 'target')
      cy.wrap(linkEl).click()
    
      cy.origin(expectedPath, { args: { expectedPath } }, ({expectedPath}) => {
        cy.url().should('include', expectedPath)
        cy.go('back')
      })
    }
    
    cy.get('a#1').then($a => {
      checkLink($a, 'https://example.com/')
    })
    

    This logs a passing test:

    enter image description here

    It also works for target="_blank" links.

    These are my two links, both work

    <a id="1" href="https://example.com">Example</a>
    <a id="2" target="_blank" href="https://example.com">Example</a>