-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
cy.wait("@route") sometimes does not catch route #2700
Comments
Could you share the test code you have written for this? Feel free to exclude any sensitive data. |
Let me know if you need more. it("can edit a file", () => {
cy.server();
cy.route(
"PUT",
`v3/project/${projectUid}/documents/${createdAttachmentUid}`
).as("updateAttachment");
checkDocumentCheckbox();
cy.get(selectors.editButton).click();
cy.get(editModalSelectors.documentName).type("updated");
cy.get(editModalSelectors.saveChangesButton).click();
cy.wait("@updateAttachment");
cy.apiCall("attachments.getOneInProject", [projectUid, createdAttachmentUid])
.its("name")
.should("contain", "updated");
}); |
Is there a chance that the request that was made sometimes does not match the Just talking out loud, cause we haven't seen any other instances where the request was happening too fast for a wait to catch. |
I don't think that could be the case, but I can't verify what that route actually was, the screen shot is an artifact of a CI build so I can't expand the side over to see the entire path. I also can't open the Routes section because it's just a screenshot from CI. Is there a way to get that info from a |
I also had this issue several times. I made the route pattern very generic, which must have matched. I think this happens because of, that your Sadly because of this undeterministic issue, I can't use the wait on request for first reuqest(s) from my app. |
Also had this issue once in a while even though my route pattern is already very generic like below. export function search(term) {
cy.server()
cy.route({
method: "POST",
url: "**/graphql",
status: 200
}).as("searchResponse")
cy.fetch(css.searchInput)
.clear()
.type(term)
cy.wait("@searchResponse")
} The app only starts hitting the backend API after I type more than 3 letters of the search term. However, even with this delayed start of API request from the app, Cypress still wasn't able to catch the route. Cypress was still waiting until it timed out even though the app has already received the response from the API and has already displayed it in UI. |
I also have the same problem where sometimes cy.route() does not work. I get it working again by making changes in my code so cypress will load the new code. Then after a while again, the cy.route() call is not registered again. This is how I load the fixtures: loadFixtures() {
return cy.fixture('data.json').then(data => {
cy.route(/"action":"data.get"/, data);
}
} My test: describe('Sort data', () => {
loadFixtures(cy);
cy.visit('/?someParam=4,55.2,8');
...
} When it works (from the network tab in chrome developer tools):
When it does not work
Also, it will sometimes work if I change the |
Unfortunately we'll have to close this issue if no reproducible example is provided. Can anyone provide a way to reproduce this? |
I have a set of tests that fails reliably on at least one of the cy.wait('@fixture') calls, but it isn't always the same call. This spec is 368 lines long, and it only started failing when I added a couple of new "it" blocks. Each of the blocks passes individually when run with .only. This leads me to believe it's a timing issue or memory leak within Cypress. Update: After noticing that more and more cy.wait calls were failing as I went along, I just refreshed the whole chrome page instead of letting cypress re-run the tests. All tests passed. I'm voting memory leak. |
@jennifer-shehane, Cypress's output window (left pane) shows a route object being setup (matching pattern), in the test object I never see the XHR entry. More over I have the exact same form that fires off the XHR request working 100% of the time, and does show a XHR entry in Cypress's left pane output.
|
@jennifer-shehane - why did we close this issue? |
This was closed due to no one providing a reproducible example that we can run locally to recreate the failure. We will reopen if someone provides a reproducible example - app and test code that can be run to see the problem. |
I'm seeing similar issues. For us it is intermittent. We have about 7 out of 55 specs which are susceptible to this type of failure. Pretty reliably at least one of them will fail on every CI run. Running the tests individually always seems to work. |
We have similar issue, however wait ignores 100% of requests like cy.route("PUT", "api/textObject/*").as("waitTextObjectReload").wait("@waitTextObjectReload"); or cy.route("PUT", "api/textObject/*", {}).as("waitTextObjectReload").wait("@waitTextObjectReload"); or cy.route("PUT", "/api/textObject/*").as("waitTextObjectReload").wait("@waitTextObjectReload"); and other variations of this command.
XHR request is displayed in cypress panel, however it's completely ignored by wait. Our app is split in two parts: 1st part is backbone, 2nd part is angular 7. The issue is reproducible in each. Requests go through nginx. |
update: cy.route("PUT", "/api/textObject/*").as("waitTextObjectReload")
makeSomethingToCallXHR();
cy.wait("@waitTextObjectReload"); this makes cypress to catch POST requests. GET requests tend to fail from time to time when written in one line like this: cy.route("GET", "api/textObject/*").as("waitTextObjectReload").wait("@waitTextObjectReload"); so we have splitted it in two parts too. |
For me it is easily reproducible, if i perform an action before waiting, and the XHR response comes before the You can see it in the OPs screenshot, his XHR ( If use the bellow code, it usually succeeds as the wait is initialized very fast after the click() const openShoppingCart = () => {
cy.server();
cy
.route({ method: 'GET', url: '/api/users/*/attributes/checkout-shipping-details' })
.as('/api/users/*/attributes/checkout-shipping-details')
.route({ method: 'GET', url: '/api/currencies' })
.as('/api/currencies')
.route({ method: 'GET', url: '/api/users/*/wishlist/saved?limit=100' })
.as('/api/users/*/wishlist/saved?limit=100')
.route({ method: 'GET', url: '/api/users/*/cart/config' })
.as('/api/users/*/cart/config')
.route({ method: 'GET', url: '/api/users/*/cart/estimate' })
.as('/api/users/*/cart/estimate');
return (
cy
.get(Cart_Badge_Header)
.should(($element) => {
expect($element).to.be.visible;
})
.click()
.wait(
[
'@/api/users/*/attributes/checkout-shipping-details',
'@/api/currencies',
'@/api/users/*/wishlist/saved?limit=100',
'@/api/users/*/cart/config',
'@/api/users/*/cart/estimate'
],
{ timeout: 20000 }
)
.then(() => {
cy.xpath(element_myCart_Tab).should(($element) => {
expect($element).to.contain('My cart');
});
})
.then(() => {
cy.get(element_loadingAnimation_shipmentPanel, { timeout: 20000 }).should('not.exist');
})
);
}; But in case I'm using this code, it will fail most of the time, as by the time cy.server() and the routes are initialised and i start the wait, the XHR already finished and the wait() will fail. const openShoppingCart = () => {
return (
cy
.get(Cart_Badge_Header)
.should(($element) => {
expect($element).to.be.visible;
})
.click()
.then(() => {
cy.server();
cy
.route({ method: 'GET', url: '/api/users/*/attributes/checkout-shipping-details' })
.as('deleteCartReq1')
.route({ method: 'GET', url: '/api/countries' }).as('deleteCartReq2')
.route({ method: 'GET', url: '/api/currencies' }).as('deleteCartReq3')
.route({ method: 'GET', url: '/api/users/*/wishlist/saved?limit=100' }).as('deleteCartReq4')
.route({ method: 'GET', url: '/api/users/*/cart/config' }).as('deleteCartReq5')
.route({ method: 'GET', url: '/api/users/*/cart/estimate' }).as('deleteCartReq6')
cy.wait(
[
'@deleteCartReq1',
'@deleteCartReq2',
'@deleteCartReq3',
'@deleteCartReq4',
'@deleteCartReq5',
'@deleteCartReq6'
],
{ timeout: 20000 }
);
})
.then(() => {
cy
.xpath(element_myCart_Tab)
.should(($element) => {
expect($element).to.contain('My cart');
});
})
.then(() => {
cy.get(element_loadingAnimation_shipmentPanel, { timeout: 20000 }).should('not.exist');
})
);
}; |
cy
.get(Cart_Badge_Header)
.should(($element) => {
expect($element).to.be.visible;
}) The above code can just be written as cy
.get(Cart_Badge_Header).should('be', 'visible') @FilepCsaba Your issues with the waits is the same as @gituser3000, the routes should be defined BEFORE the calls to the routes happen. WorkaroundYou should NEVER have a cy.route('GET', '/thing').as('getThing')
cy.wait('@getThing') // <---- WILL NEVER WORK It should be like this: cy.route('GET', '/thing/*').as('getThing')
// <--- Do the thing that triggers the XHR request
// <--- maybe .click() on something or cy.visit() a url
cy.wait('@getThing'); |
I have similar issue. I call I am not sure why. Here is my code snippet. beforeEach(() => {
// runs before each test in the block
cy.server();
});
it('Create App Test', () => {
cy.checkSignin(); // this is my customization function. it works without error.
//This part is just issue expect()
cy.get('div.ant-notification').should($note => {
expect($note, 'Login Success Notification').to.contain(
'Login success!',
);
});
cy.route('POST', Cypress.env('graphqlUrl'), 'fixture:apps/getApp.json').as('getAppLists');
cy.wait('@getAppLists'); |
@jennifer-shehane Thank you, putting all .route() in before and waiting in tests, works. |
@jennifer-shehane I have added beforeEach(() => {
// runs before each test in the block
cy.server();
}); And I have to add several routes with same url - Of course, its request parameters and return json value are different for each other. How can I put all routes with same url at same place and get its return value using wait()? |
The issue I'm seeing related to this is that the wait is occurring after page load due to a redirect. At which point is too late. Test: beforeEach(function() {
cy.loginByCSRF();
cy.visit('/account/update-email')
});
it('Successfully submit the form', function() {
cy.server();
cy.route('POST', '/account/update-email').as('postBody');
let submittedEmail = '';
//Calls function in commands.js to generate a random name
cy.getRandomName().then(function(name) {
submittedEmail = name;
cy.get('#new_email').clear().type(name + '@foobar.com');
cy.get('#new_email_confirm').clear().type(name + '@foobar.com');
});
cy.get('#password').clear().type(resetEmail);
cy.get('.form-action > .button').click().wait('@postBody');
cy.get('@postBody').then(function(xhr) {
expect(xhr.status).to.eq(302);
});
}); |
@clock-rick I'd probably add an assertion about the url before defining the wait. cy.get('.form-action > .button').click();
cy.url().should('include', 'account');
cy.wait('@postBody'); |
We were provided one example of a route definition never catching during cy.wait when the request was clearly made here, but marketly the request never resolves: #3427 (comment) |
The problem is that sometimes the Request is exactly the same exempt for the request body (which I both want to catch) So say create a route
I then setup my But the application sends 2 post requests to
Now I can only cath the second one by adding a route just before the second request. Cy.route('POST','https://Iamanawesomeurl.com').as('post1')
cy.click(fireroute)
cy.wait('@post1').then((xhr)=>{
writefilebody as body 1
})
Cy.route('POST','https://Iamanawesomeurl.com').as('post2')
cy.wait('@post2').then((xhr)=>{
writefilebody as body 2
}) This seems to me the only way to catch both instances? isn't that correct? |
Cy.route and then wait for that request to complete - Is this the only way to add synchronised wait in cypress? what if there is no xhr request getting captured but still application has some wait time(some business logic layer computations) and after that dry wait (variable amount of time, depends on data provided and user load ) time xhr gets triggered and one button gets change from in progress to completed. Unable to find way to ass wait in this scenario. |
@jennifer-shehane What is the reasoning behind adding an assertion before the wait? |
I experienced the same issue since last week and for some obscure reasons, adding a timeout to the wait did the trick. In the original post, adding a responseTimeout like this cy.wait("@updateAttachment", {responseTimeout: 15000}); did the trick. The error message is misleading. So is the fact that the WAIT appears after the request in the console log. Is cypress in fact catching response return instead of entire cycle (send/receive)? |
I think I finally found a reproducible example. Github's login response is very fast such that this test always fail on me. describe('Capturing data sent by the form via POST method', () => {
before( () => {
Cypress.config('baseUrl', 'https://github.com');
cy.server();
cy.route({
method: 'POST',
url: '/session'
}).as('githubLogin');
});
it('should capture the login and password', () => {
cy.visit('/login');
cy.get('#login_field').type('username');
cy.get('#password').type('password');
cy.get('input[value="Sign in"]').click();
cy.wait('@githubLogin').then( xhr => {
cy.log(xhr.responseBody);
cy.log(xhr.requestBody);
expect(xhr.method).to.eq('POST');
})
});
}); Reddit is not as fast as Github so a similar test always pass. describe('Capturing data sent by the form via POST method', () => {
before(() => {
Cypress.config('baseUrl', 'https://www.reddit.com');
cy.server();
cy.route({
method: 'POST',
url: '/login'
}).as('redditLogin');
});
it('should capture the login and password', () => {
cy.visit('/login');
cy.get('#loginUsername').type('username');
cy.get('#loginPassword').type('password');
cy.get('button[type="submit"]').click();
cy.wait('@redditLogin').then(xhr => {
cy.log(xhr.responseBody);
cy.log(xhr.requestBody);
expect(xhr.method).to.eq('POST');
})
});
}); I was hoping to capture this GitHub login request. This is how the test pass in Reddit. The result is the same even if I use: cy.visit('/login', {
onBeforeLoad: (win) => {
delete win.fetch;
}
}); |
I came here trying to figure out why |
Also having this issue! The request is not captured by cypress so it's not mocked and the live API is called instead. There is now a reproducible example so the thread should be reopened? |
I have the same issue :/ |
Another vote here for the issue to be reopened, this just costed me half of a working day. |
I was having this same issue just now. My issue was that I was using in my I tried using You should see your network requests appear in the steps pane. If they don't, you might not have the Fetch polyfill enabled. as @jennifer-shehane mentioned the order of ops is:
hope this helps! |
Experiencing the same issue. Please reopen the issue |
+1 - we see this pretty frequently and have to workaround with a bunch of assertions that elements on the page exist as a result of a route rendering. Code example: it('can be loaded', () => {
cy.server();
cy.route('GET', '/sales').as('getSales');
cy.siteSignIn('test-user');
cy.visit('/account/sales');
cy.wait('@getSales');
cy.get('#accountDashboardApp').should('be.visible');
cy.get('.screen-sales').should('be.visible');
cy.get('.sales').should('be.visible');
cy.get('.tips').should('be.visible');
cy.fullRegressionSnapshot('Sales Dashboard Page');
}); Yet, often this fails when the When this fails, we see the We need a reliable way to wait for a request to finish loading, whether it's fast or slow. It'd be nice if we could have some kind of listener or way to call a wait before the command that will trigger the request, so it's for certain waiting before the request starts. |
I have the same problem |
This comment has been minimized.
This comment has been minimized.
While we were never given a clear reproducible example of this bug (I was never able to reproduce from #2700 (comment) either), I believe this was likely occuring for some people. There were some documented cases of similar bugs here: #5999 ResolutionWe suggest migrating If you're experiencing a bug after upgrading to |
Steps to reproduce:
2- Call it once The cy.wait("@ApiCall") will think that the API has been already called in the second function call and the code will continue running (because of the first time we called the function). |
Many people have problems but you are simply closing issues, cool |
some problem here |
Because Cypress doesn't use promises, you can't use
Does anyone know of a similar capability that Cypress does have? |
@jsdevtom Check out our community chat, it can be helpful for debugging or answering questions on how to use Cypress. |
lol, so unprofessional |
Current behavior:
Occasionally (no, I do not have a reproducible example), when I wait for a route the route will complete before the call to
cy.wait("@theRoute")
is made, then the wait will time out. This happens a very small fraction (<1%) of the time and the only consistency that I can find is it happens after the test.click()
s something, then immediately waits for a route, but it doesn't seen to be any tests in particular. It is like the route returns too fast for cypress to see.See screenshot below - the line above the failed wait is the route it is supposed to wait for.
Desired behavior:
I think this is obvious
Steps to reproduce:
I don't have any - I know this is super helpful.
Versions
Cypress 3.1.0
Chrome 70
The text was updated successfully, but these errors were encountered: