Basically, I want to login once before all my tests in all files are executed.
Should I call my login command in each test file using the before hook or is there any way to do it once before all tests?
Short answer: You can write your login command in a before hook within the supportFile (the file that is loaded automatically before your other spec files). This before hook will run before any of the code in your other test files.
Recommendations: That being said, this approach leaves little flexibility for variation in your individual test files that you may want in the future like:
What if you want to seed the database differently for one test?
What if you want to log in as a different user with different permissions?
What if you need to do something in onBeforeLoad once?
I would recommend just having the login command in a before hook in each individual spec file.
I would also further recommend having your login command in a beforeEach hook to avoid sharing any state in between tests.
describe('Hooks', function() {
before(function() {
// runs once before all tests in the block
})
})
https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests.html#Hooks
I would login before EACH test because there could be things that happen in a previous test that affects the results of the current test. With a fresh login, you're starting with a clean state every time. If you want to test a "chain" of unrelated actions (action A THEN action B), then write that as a separate test, but have basic functionality in individual tests.
describe('/page'), () => {
beforeEach(() => {
cy.login() // custom command that handles login w/o UI
cy.visit('/page') // go to the page you are testing
})
// tests
})
You should include a beforeEach block in every test file. This block should login and navigate to the page in question.
I would wrap the function to execute in a before block, as others already suggested.
Now, looking at the docs, I would make that happen in the cypress/support/index.js file.
Related
We have a platform with a lots of workflows and a lots of tests. Right now for each test we have to complete a long workflow. In order to speed up this, I want to share the context or the browser, with all the cookies, the url, and all the data between all the it inside each describe.
I could also crete just one it and put everything inside but i'll prefer to maintain all the it functions to have all more organizated.
I know that i'm dealing with anti patterns.. but this will improve significantly the speed of the tests.
So.. is there a way to acomplish this? I can't find anything.
Thank you!
cy.session() should get you most of the way there. It allows you create a session, from which Cypress will cache most of the browser context. The next time Cypress encounters the session command, it will check to see if it has created a session with the same id, and if it has, it will use those cached values. Otherwise, it executes the contents of the cy.session() command.
From the docs:
Cache and restore cookies, localStorage, and sessionStorage (i.e. session data) in order to recreate a consistent browser context between tests.
Once created, a session for a given id is cached for the duration of the spec file. You can't modify a stored session after it has been cached, but you can always create a new session with a different id.
In order to reduce development time, when running Cypress in "open" mode, sessions will be cached for spec file reruns. To persist a session across multiple specs, use the option cacheAcrossSpecs=true
And their example using cy.session inside of a login command.
Cypress.Commands.add('login', (username, password) => {
cy.session([username, password], () => {
cy.visit('/login')
cy.get('[data-test=name]').type(username)
cy.get('[data-test=password]').type(password)
cy.get('form').contains('Log In').click()
cy.url().should('contain', '/login-successful')
})
})
I need a solution. I have a lot of spec files with tests and after each of them I use cy.logout command.
I want to avoid write this logout function each time and want it global.
But when I tried add this function in index.js file it was called at the beginning of each test because index.js works perfect only with beforeEach but not with afterEach.
What should I do?
Thanks
[EDIT]
I just find out that problem was provoke by my mistake in code in second test, so the only problem I have with Cypress is that I dont get any information where I made my mistake because Cypress show me that problem is afterEach hook and nothing else.
If you want your logout runs only once for each of your spec file, and not after each of your test within the file, you must use after instead of afterEach.
after(() => {
cy.logout()
})
Using afterEach() or beforeEach() block in support/index.js. Refer below page to run a "global" hook
https://filiphric.com/cypress-basics-before-beforeeach-after-aftereach
I have the following use case. There are two sites on different domains. usersettings.com (written in ExtJS) and myapp.com (angular app). Usersettings.com contains configurations that would alter the UI of myapp.com. Please see the screenshot for example.
Now since I need to modify user-settings to different ones before running all the test files. What would be the best approach to solve this use case in Cypress.
One approach I am planning to use is a single Cypress spec file to visit usersettings.com and alter the configuration of the user-settings site. I can achieve it by coding it as a support file. Post that, I can run my entire test suite (having multiple *.spec.js files). The question is it possible and is it a good approach against other alternatives (if any)?
It can be done by setting up the test in a separate test case
//Global setup
context('doubleDomainTest', () => {
it('firstDomain', function () {
//Code to run on the firstDomain
})
it('secondDomain', function () {
//Code to run on the secondDomain
})
})
I am trying to debug in nightwatch.
When I put in a console.log it prints before the test runs - while its doing some sort of construction/compiling of the test.
I tried also visual studio code debugger and same thing - the breakpoint hits before the tests are actually run.
thanks for help - mark
"nightwatch" is built on node.js. Node.js executes statements asynchronously. If you write console.log();, it will be executed asynchronously.
The statements you write using browser (or client) object (e.g. browser.url(); , browser.click(); etc.) will be queued up at Selenium Server. They are also executed asynchronously by node.js but are queued up at selenium server.
To perform console.log() in sync with other statements in nightwatch, use .perform(). You will get output in sync with other statements.
Example
var elementValue;
browser
.getValue('.some-element', function(result) {
elementValue = result.value;
})
// other stuff going on ...
//
// self-completing callback
.perform(function() {
console.log('elementValue', elementValue);
// without any defined parameters, perform
// completes immediately (synchronously)
})
.end();
For debugging purpose, you can stop the execution to find out element values or check the browser related data. Use this command: browser.pause(); (or client.pause();). Do not pass any timer here. It will stop the execution.
As you don't really have an example, or some code that you run, i can only give you the general direction you can try in order to fix the issue.
This happens because your code is ran asynchronously (cause that's how javascript works) and everything that is not browser/html related will run before your browser starts your actual test. I suggest you should try using callbacks in order avoid printing your check msgs first (this way you link the console.log to your code that depends on the browser and it will run only after this finishes. If you do that, the debugging with console log will actually work.
Maybe you can learn here how to do that, as an example.
To be able to test my web service, I need to be logged in.
I've wrote a casperjs test for the login funcionality, but I would like to reuse that in all of my future tests.
Is there a way to modularize the login routine I've already wrote, and have it to run at each test's start function?
You can either write a module or extend the casper object.
In a test context, this gist may be useful as well.