Reputation: 4320
I have following test
it('does not trigger request', () => {
cy.shortcutThatTriggersRequest()
cy.route({
method: 'POST',
url: '[url]',
onRequest: () => {
cy.contains('request was invoked').should('exist')
},
})
cy.wait(1000)
})
which does what I want to do - if given request has happened, it will fail the test and if it didn't then the test will pass.
There're two troublesome things with it though:
Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.
; I can't omit the wait
as otherwise the test will be marked as passing (test ends while request is being resolved, test is marked as passing and failure happens afterwards); this happens only when request was made (which makes sense as route
isn't being triggered, so no contains
can trigger at the same point as wait
I guess)cy.contains('request was invoked').should('exist')
to mark the test as failing. I don't want to do that; while no such string will ever exist, it's a workaround; ideally I'd want to co cy.fail()
but I don't see such methodUpvotes: 2
Views: 2194
Reputation: 895
The most concise solution (with Cypress 13.7) I came up with was simply throwing an error in the route handler. It's not an explicit assertion, but the test still fails if the endpoint get's called
cy.intercept("...", () => {
throw new Error("Should not happen");
})
Upvotes: 1
Reputation: 55
I have used following setup with module variable.
cy.wrap
failed inside cy.intercept
. Maybe Cypress.env
could be used but I guess it would leak to another test.
let requestPerformed;
beforeEach(() => {
requestPerformed = false;
});
it('', () => {
cy.intercept('/route', () => {
requestPerformed = true;
});
cy.someTrigger();
cy.wrap(requestPerformed).should('be.false');
});
I believe it could be generalized to a command.
Upvotes: 1
Reputation: 4320
Ok, to achieve this, I've used following:
it.skip('does not trigger products requests', () => {
Cypress.on('fail', (error, runnable) => {
if (error.message.indexOf('Timed out retrying') !== 0) throw error
})
cy.server()
cy.route({
method: 'POST',
url: '[url]',
}).as('products')
cy.shortcutThatTriggersRequest()
cy.wait('@products', {
requestTimeout: 1000,
}).then((xhr) => {
assert.isNull(xhr.response.body)
})
})
If a timeout is reached, it will be handled within fail
and thus test will pass. If it gets inside then
then the test will fail.
There's an additional issue here, that if multiple routes are checked (cy.wait['route1', 'route2']
) and one of them doesn't exist, then the test will pass even though one of the assertions specifies that it shouldn't, for example:
it.skip('does not trigger products requests', () => {
Cypress.on('fail', (error, runnable) => {
if (error.message.indexOf('Timed out retrying') !== 0) throw error
})
cy.server()
cy.route({
method: 'POST',
url: '[url]',
}).as('route1')
cy.route({
method: 'POST',
url: '[url]',
}).as('route2')
cy.shortcutThatTriggersRequest()
cy.wait(['@route1', '@route2'], {
requestTimeout: 1000,
}).then((xhrs) => {
assert.isNull(xhrs[0].response.body)
assert.isNull(xhrs[1].response.body)
})
})
passes even though there was a request to one of those endpoints (I assume it's a bug caused by handling of onfail
. What needs to be done, is the request assertions need to be sequential:
cy.wait('@route1', {
requestTimeout: 1000,
}).then((xhr) => {
assert.isNull(xhr.response.body)
})
cy.wait('@route2', {
requestTimeout: 1000,
}).then((xhr) => {
assert.isNull(xhr.response.body)
})
As far as I can see we can't check the type of error
in onfail
as it's always CypressError
irregardless of what caused it
Upvotes: 3