Reputation: 1370
I'm a Cypress newbie and need to add basic auth to all cy.visit()
calls.
The auth credentials are dependent on the deployment (i.e. they are specific to the 'baseUrl' which we set in the environment config files).
Currently, I have;
cy.visit("/", {
auth: {
username: '...',
password: '...'
}
});
What I want is to move the 'auth' object to the evg config files so I only need cy.visit("/")
in the specs.
Upvotes: 2
Views: 15289
Reputation: 27016
The topic is more complex than it might seem to be at first sight. For example
are a few but there are even more important questions coming up when you dig deeper into this topic. Below I summarized the most important ones and provided some links so you're able to deep dive into the topic.
I found very useful tips in Dr. Gleb Bahmutov's article "Keep passwords secret in E2E tests" regarding how to write code in Cypress that logs in a user in but does not write the password into the log. It also gives hints how to configure and where to store passwords safely.
Key topics in this article are (only short examples given here, there is so much more in the article):
Do not hardcode passwords. Use environment variables, e.g.
const password = Cypress.env('password')
Then there are several ways where and how to store the value, one is using the cypress.env.json
file (as described here). You can find more ways in the link at the end of this answer.
Visible password. Avoid logging it by adding the log: false
parameter, e.g.
cy.get('[name=password]').type(password, {log: false})
If you want to hide a non-password field on screen during the running test, such as the email address etc., add .invoke('attr', 'type', 'password')
after the .get(...)
statement and before typing, which will mask it on screen
Validate password, e.g.
if (typeof password !== 'string' || !password) { throw new Error('Missing password value, set using CYPRESS_password=...') }
Avoid UI login (advanced topic)
"Find the recipe that matches this method among Cypress Logging in recipes"
Continuous integration (advanced topic)
This topic covers how to use E2E testing in a CICD pipeline.
Plugins
How can they be dangerous? They could reveal your password.
Conclusions
"Keeping sensitive information out of public logs, screenshots and videos is a very important and ongoing concern. Make sure that every commit even if it only changes the tests goes through code review."
More hints regarding about correcty define and use environment variables in tests:
Upvotes: 0
Reputation: 1878
This is how I handled Basic Auth with Cypress using cy.request:
cy.request({
method:'POST',
url:'myURL',
body: {
Name: name,
userId: userId,
languageId: languageId
},
headers: {
authorization: 'Basic lasdkfjlsdyZHRoYXRpa25vdzp'
},
}).then(response => {
expect(response.status).to.equal(201)
})
})
Basically, the "headers" object inside the cy.request do the magic.
Upvotes: 0
Reputation: 73
If you plan to reuse the authentification then is better to create a separate method for authentication e.g.:
1. Create a new custom command in `cypress/support/commands.js, since it is loaded before any test files are evaluated via an import statement in your supportFile (cypress/support/index.js by default).
Cypress.Commands.add('login', () => {
// (you can use the authentification via API request)
return cy
.request({
method: 'POST',
url: your_url,
form: true,
body: {
username: Cypress.env('username'),
password: Cypress.env('password'),
grant_type: 'password',
client_id: your_clientId,
client_secret: your_clientSecret,
scope: 'openid',
},
})
})
2. Then use it in your test:
describe('My Test Name', () => {
before(() => {
cy.login();
});
it('should visit my base URL', () => {
cy.visit('/');
});
});
Note 1: Check how to set the environment variables here: Cypress.io: Environments Variables
Note 2: Check how to use the custom commands here: Custom Commands - Correct Usage
Upvotes: 2
Reputation: 3690
If you have HTTP basic auth for all pages add this code to your cypress/support/commands.js
:
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
options = options || {}
options.auth = {
username: 'replace_this_with_the_username',
password: 'replace_this_with_the_password'
}
return originalFn(url, options);
});
Upvotes: 2
Reputation: 1425
EDIT: since your syntax is correct - I will just share a way I use to do it in my tasks.
If your auth is working correctly you can make custom command - visitAndAuthorise like this for example:
Cypress.Commands.add("shopAdmin_visitAndLogin", (url) => {
cy.log('shopAdmin_visitAndLogin')
cy.visit(url)
cy.get('[data-qa="emailInput"]')
.type(Cypress.env('credentials').email)
cy.get('[data-qa="passwordInput"]')
.type(Cypress.env('credentials').password)
cy.get('[data-qa="loginButton"]')
.click()
cy.get('[data-qa="logOutButton"]')
.should('be.visible')
})
And your cypress.env.json file would need to include an object for the credentials like this:
{
"credentials": {
"email": "[email protected]",
"password": "myPassword"
}
}
Or following your syntax:
Cypress.Commands.add("shopAdmin_visitAndLogin", (url) => {
cy.log('shopAdmin_visitAndLogin')
cy.visit(url, {
auth: {
username: Cypress.env('credentials').username,
password: Cypress.env('credentials').password
}})
})
Upvotes: 1