Is there any way to mark a failing test as an expected failure? I have a test that is constantly failing, but it's a known bug and the ticket for this issue has been reported a while ago.
I would just use xit instead of it to skip the test. Above it I would add a comment with a link to the bug ticket. When it is done with xit, the test is shown as pending.
In this scenario, it is better to skip the test which are failing if you don't want to delete the test and want to keep it once you know the reason of the test failure. Same is also mentioned in the official documentation of jest.
So, basically, there are two ways to skip any test or test suite.
prefixing the test or it or describe with x
xdescribe(("test suite will be skipped") => {
xtest(("this test is also skipped but don't use it with xdescribe") => {
expect(true).toBe(true);
})
xit(("skip it test") => {
expect(true).toBe(true);
})
})
skip() api of test, it or describe
describe.skip(("test suite will be skipped") => {
test.skip(("this test is also skipped but don't use it with describe.skip") => {
expect(true).toBe(true);
})
it.skip(("skip it test") => {
expect(true).toBe(true);
})
})
Related
Is there a way to force a test to fail in Detox? I haven't found anything in the documentation that says this can be the case. I am comparing two IDs that are hidden in an element and screen of my app and if they don't match, I want to fail the test.
if (element.id === screen.id) {
do
}
else {
*fail test*
}
it(`should invite User`, async () => {}
Or is it as easy as just throwing an error? Thanks
Detox itself delegates test logic to a test runner.
Detox delegates the actual JavaScript test-code execution to a dedicated test-runner. It supports the popular Jest and Mocha out of the box.
If you are using jest as the underlying test runner, you could just use its fail method as follows.
if (element.id === screen.id) {
do
}
else {
fail('test fails');
}
In mocha you could use the following function.
assert.fail("actual", "expected", "Error message");
We could also abuse the detox high level api to achieve the same (but less readable).
await waitFor(element(by.id(notVisible.id))).toBeVisible().withTimeout(5);
According to documentation, this hook should only execute once per suite run (once every cypress run call), but this seems to be executed before every single spec. Is this a bug? Or am I doing something wrong?
Cypress.Cookies.defaults({
preserve: ['cookie']
})
before(() => {
cy.log("Should only run once")
})
});
The before() hook runs once per spec file, not once per cypress run.
It looks like you want the Before Run API
on('before:run', (details) => {
/* ... */
})
I have an API automation test suite using Cypress and one of the issue I am facing in one of the test is to validate the response headers.
For some reason, I am not able to read the response headers using Cypress.
The code is below
cy.request({
method:'GET',
url:Cypress.env("Authorisationurl")+tokenId+'&decision=allow&acr_values=1',
followRedirect: false,
headers:{
'Accept': "/*"
}
}).then((response) => {
const rbody = (response.body);
cy.log(response.status)
//THIS GOT ASSERTED TO TRUE
expect(response.status).to.equal(302)
//OPTION1
cy.wrap(response.headers['X-Frame-Options']).then(() => {
return response.headers['X-Frame-Options'];
});
//OPTION2
return response.headers['X-Frame-Options']
//OPTION3
return response.headers
})
None of the above options gives me the header information. Infact I am confused with the order of execution too.
This is my output.
for the following code.
const rbody = (response.body);
cy.log(response.status)
cy.log(response)
expect(response.status).to.equal(302)
cy.log(response.headers)
cy.log(response.headers['X-Frame-Options'])
return response.headers['X-Frame-Options']
Also, not very sure what Object{9} indicates. Can anyone please explain what is happening here.
I am aware of Cypress flow of execution and the code is written in then block as a call back function.
Option 3 is very scary as it gives an error
cy.then() failed because you are mixing up async and sync code.
In your callback function you invoked 1 or more cy commands but then returned a synchronous value.
Cypress commands are asynchronous and it doesn't make sense to queue cy commands and yet return a synchronous value.
You likely forgot to properly chain the cy commands using another cy.then().
The value you synchronously returned was: Object{9}
Can anyone please help me here as in what is the correct way of doing it. I know Cypress is very quick and easy to use but to move away from Selenium, we need to make coding easier for developers with meaningful error message. Object{9} is not very helpful.
Also, Do I need to use Cy.log ? As the sequence of prints is not what I have written in the code. Thanks very much for your time on this.
Please use like this:
JSON.parse(JSON.stringify(response.headers))["X-Frame-Options"];
The "mixing async and sync code" message is basically saying you should keep the .then() callback simple.
But you can chain more than one .then() to run the async and sync code separately.
Use an alias to "return" the value. Since cy.request() is asynchronous, you will need to wait for the value and the alias pattern is the most straight-forward way to do this reliably.
WRT Object{9}, it's the result of the way Cypress logs complex objects.
Don't use cy.log() to debug things, use console.log().
cy.request( ... )
.then(response => {
expect(response.status).to.equal(200) // assert some properties
})
.then(response => response.headers) // convert response to response.headers
.as('headers')
cy.get('#headers')
.then(headers => {
console.log(headers)
})
Since this was originally posted a year ago and Cypress has had many versions since then, the behavior may have changed, however this works in Cypress 11.
You can access the response.headers array as you would normally expect, however the casing of the header name was not as expected, Postman reported the header as X-Frame-Options, but Cypress would only allow me to access it if I used a lower-cased version of the header name (x-frame-options).
cy.request({
url: '<Url>',
method: 'GET',
failOnStatusCode: false
})
.then((response) => {
expect(response.status).to.eq(200);
expect(response.headers["x-frame-options"]).to.equal("SameOrigin");
})
.its('body')
.then((response) => {
// Add your response testing here
});
});
I have the following test for a custom Cypress command of mine:
it('can navigate to a url', () => {
const history = createHistory();
cy.window().then(win => ((win as any).__chh__history__ = history));
cy.spy(history, 'push');
history.listen((location, action) => {
expect(action).to.equal('PUSH');
expect(location.pathname).to.equal(PATH);
expect(location.state).to.equal('foobar');
});
cy.navigate(PATH, 'foobar');
cy.wait(0).then(() => {
expect(history.push).to.have.been.called;
});
});
The command works fine, but if I remove the cy.wait(0), only doing the expect, then the test fails.
I assume it's because the cy.navigate command (added via Cypress.Commands.add) is queued, like other Cypress commands, meaning the expect actually runs before any of the Cypress commands have even started?
If so, that's fine and as expected of course, but is there a way in Cypress tests to queue things, without using cy.wait(0)?
For example when I'm checking elements, I can use cy.get(something).should($el => expect(...)), but in this case, there's nothing to "should on"... I could of course cy.get('body') or whatever, but I don't really want to get anything in this case. 🤔
The docs show use of a naked expect() after the spy has been established,
cy.spy(util, 'addListeners')
App.start()
expect(util.addListeners).to.be.called
but I think this is misleading, since expect() runs immediately but intervening Cypress commands may have inherent delays or reties, and can't be guaranteed to complete before the expect is executed.
Two other ways to test this are:
Ensure the expect is only run after your custom command
cy.navigate(PATH, 'foobar').then(() => {
expect(history.push).to.have.been.called;
})
Put the expectation into the Cypress command queue
cy.navigate(PATH, 'foobar');
cy.wrap(history).its('push').should('have.been.called')
I have a reasonably special use-case:
I have an input field which issues a search when the user has stopped typing for 500ms. This is developed as a reusable add-on.
I would like to write an acceptance test for this but I cannot make the tests pass properly. The first passes, the second doesn't.
Now, the Ember runloop has a nice description but it's behaviour is really "something else".
This is my helper to timeout the runloop:
import Ember from 'ember';
export default Ember.Test.registerAsyncHelper('pauseFor', function (time) {
return Ember.Test.promise(function (resolve) {
Ember.run.later(resolve, time);
});
});
And this is how I use it
it('should do something after 500ms', function () {
visit('/');
fillIn('.search-input', 'a');
pauseFor(500);
andThen(function () {
// do my assertions/expectations here...
});
});
This is the error I get:
The weird thing is that I have 2 test cases and the first passes happily.
I guess my question is:
How to do this properly? What am I missing here or what am I doing wrong? How can I just simply timeout the test case?
Thanks for the halp!