Cypress with Auth0.com login and redirects - cypress

We have changed our login page so it's now redirecting to auth0.com and then back to our domain after you login to auth0. The issue is now when I login I get redirected to our QA environment which requires authentication so once the test submits the form I get a 401.
Before auth0 I was getting around the 401 by overwritting the visit function passing in a auth header.
If I try to visit our QA environment first before going to our login page I get
You may only cy.visit() same-origin URLs within a single test.
I've seen other questions asked about auth0 but not with also requiring authentication in the redirect, is it possible to still run tests on our QA environment?

While the Cypress team works to resolve max 1 site... support visiting multiple superdomains in one test on work around I have used in the past is this: detailed again below.
In commands.js
// -- Save localStorage between tests
let LOCAL_STORAGE_MEMORY = {};
Cypress.Commands.add('saveLocalStorage', () => {
Object.keys(localStorage).forEach(key => {
LOCAL_STORAGE_MEMORY[key] = localStorage[key];
});
});
Cypress.Commands.add('restoreLocalStorage', () => {
Object.keys(LOCAL_STORAGE_MEMORY).forEach(key => {
localStorage.setItem(key, LOCAL_STORAGE_MEMORY[key]);
});
});
// -- Visit multiple domains in one test
Cypress.Commands.add('forceVisit', url => {
cy.window().then(win => {
return win.open(url, '_self');
});
});
In test.spec.js
/// <reference types="cypress" />
context('Force Visit', () => {
it('should be able to visit and assert on two domains', () => {
cy.forceVisit('https://example.cypress.io');
cy.title().should('eq', 'Cypress.io: Kitchen Sink');
cy.forceVisit('https://www.google.com');
cy.title().should('eq', 'Google');
});
});
context('Auth Flow', () => {
before(() => {
cy.forceVisit('<auth url>');
cy.get('<username input>').type('<username>');
cy.get('<password input>').type('<password>');
cy.intercept('POST', '<auth login request>').as('auth');
cy.get('<submit button>').click();
cy.wait('#auth');
});
afterEach(() => {
cy.saveLocalStorage();
});
beforeEach(() => {
cy.restoreLocalStorage();
// Preserve Cookies between tests
Cypress.Cookies.defaults({
preserve: /[\s\S]*/,
});
});
it('should be able to start in authorized state', () => {
cy.visit('<site url>');
});
});

Related

When I want to switch from A tab to B then it shows blank page using cypress

After login when I switch from Tab A to Tab B then it shows blank page,
How i maintain session of Tab A. After performing activity on Tab A, I move to Tab B and start performing activity on Tab B
If the session has not been created yet, it will run the callback fn code, otherwise, it will only restore the session (and you'll have to visit the page again).
So, I think changing before hook to a beforeEach and adding a visit after the login method would work:
beforeEach(() => {
login('user1')
cy.visit('http://#')
})
But this approach will visit the page twice in the first run, to avoid this personally I would use the login with it's code in the before hook and restore and visit the page in the beforeEach.
const login = ({ sessionId, username, password }) => {
cy.session(sessionId, () => {
cy.visit('http://#')
cy.get('[type=text]').type(username)
cy.get('[type=password]').type(password)
cy.get('[type=submit]').click()
})
}
describe('test', () => {
const sessionId = 'Login with valid credentials'
before(() => {
login({ sessionId, username: 'user1', password: 'Test123' })
})
beforeEach(() => {
cy.session(sessionId)
cy.visit('http://#')
})
it('Tab A', () => {
cy.get('#A').click()
})
it('Tab B', () => {
cy.get('#B').click()
})
})
Please let me know if it solves your problem.

How to change the domain in cypress?

Suppose i have one test case in that i have visit two different url can it is possible in cypress!
google.com
youtube.com
describe('validate the functionlity of change the domain',()=>{
it('verify the functionlity of change domain',()=>{
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false
})
cy.origin('http://www.webdriveruniversity.com',()=>{
cy.visit('/Contact-Us/contactus.html')
})
})
})
i have tried with this one it is working but my problem is that i want to use two different url in one test case
If you need to visit two separate domains, such as the two you provided, you can do that by having separate cy.origin() calls.
it('tests two separate domains', () => {
cy.origin('https://www.google.com', () => {
cy.visit('/');
// code
});
cy.origin('https://www.youtube.com', () => {
cy.visit('/');
// code
});
});
If you run the above, with cy.wait() after the cy.visit() commands, you'll see that Google and Youtube are navigated to.

Cypress.Cookies.preserveOnce('session_id') isn't working when called in afterEach hook

I'm working with cypress tests and I want to avoid having to log in before each test. so, I wanted to preserve the cookies in each test file.
The log statement in the afterEach hook is triggered, however cookies are cleared in the second testcase.
describe('Users Page Scenarios', () => {
before(() => {
myApp.pages.Login.navigate();
myApp.pages.Login.login(
credentials.globalAdmin.email,
credentials.globalAdmin.password
);
});
beforeEach('navigate to users page before each test', () => {
myApp.sharedComponents.Header.navigateToUsers();
});
afterEach(() => {
Cypress.Cookies.preserveOnce('session_id');
cy.log('test');
});
describe('Users List', () => {
it('Should redirect the user to users page after clicking on users in the navigation header', () => {
cy.url().should('eq', `${Cypress.config().baseUrl}/user`);
});
})
describe('New User Creation', () => {
it('Should open new user modal after clicking on invite administrator', () => {
myApp.pages.Users.UsersList.inviteAdministrator();
cy.url().should('eq', `${Cypress.config().baseUrl}/user/new`);
});
it('Should create a new user successfully', () => {
myApp.pages.Users.UsersList.inviteAdministrator();
myApp.pages.Users.UsersInfo.createNewUser(user.generateUser());
})
});
The docs indicate that Cypress.Cookies.preserveOnce('session_id') is used in beforeEach().
Looks like after is too late.
describe('Dashboard', () => {
before(() => {
// log in only once before any of the tests run.
// your app will likely set some sort of session cookie.
// you'll need to know the name of the cookie(s), which you can find
// in your Resources -> Cookies panel in the Chrome Dev Tools.
cy.login()
})
beforeEach(() => {
// before each test, we can automatically preserve the
// 'session_id' and 'remember_token' cookies. this means they
// will not be cleared before the NEXT test starts.
//
// the name of your cookies will likely be different
// this is an example
Cypress.Cookies.preserveOnce('session_id', 'remember_token')
})
If you have localStorage or sessionStorage to preserve, or you have not identified all cookies correctly, try with cy.session()
beforeEach(() => { // must be beforeEach()
cy.session('mySession', () => { // preserves localStorage, sessionStorage, cookies
myApp.pages.Login.navigate();
myApp.pages.Login.login(...); // only called once (despite beforeEach())
})
})

Cypress - Write a file everytime the url changes

I am running a cypress test, in which I visit a url that has many redirects.
I wish to get all redirects and write them to a file.
Doing this code works somehow
describe(`Test Offer URL`, () => {
let urls = [];
it(`Visits the offer url ${Cypress.env(
"offer_url"
)} with a pre-defined user agent of ${userAgent}`, () => {
cy.visit(Cypress.env("offer_url"), {
headers: { "user-agent": userAgent },
});
cy.on("url:changed", (url) => {
urls.push(url);
});
cy.log(urls);
});
after(() => {
cy.writeFile("cypress/results/offers.json", {
baseUrl: Cypress.env("offer_url"),
userAgent,
redirectUrls: urls,
});
});
});
so with this code cy.on("url:changed", (url) => { urls.push(url);});
I am able to get all the needed urls, I can check this with cy.log(urls)
But when i write the file I wont have them all
I thought to run the cy.writeFile() function inside of the url onChange trigger, but I get an error :
I tried chaining with a .then(() => cy.writeFile()) but it will only write the file one time
Any clues of how I could resolve this.

Problem with CSRF protected Login in Cypress

I try to test a PHP Symfony application via Cypress.io but got problems with a custom login command which uses CSRF protection.
My command looks like this:
Cypress.Commands.add('login', () => {
cy.request('/login')
.its('body')
.then((body) => {
const $html = Cypress.$(body);
const csrf = $html.find('input[name=_csrf_token]').val();
cy.request({
method: 'POST',
url: '/login',
failOnStatusCode: false,
form: true,
body: {
username: 'user',
password: 'password',
_csrf_token: csrf,
},
})
});
});
This is the test spec:
describe('Masterdata Test', () => {
beforeEach(() => {
cy.login();
cy.visit('/masterdata/autoselector');
});
it('highlights the correct register', () => {
cy.get('.registerTab.bg-white').contains('Masterdata');
});
});
When I run the tests it seems that the login somehow works (it returns a 200 status code) but when it visits the url which should be checked it redirects to login again. (See picture below)
I already checked that the CSRF token is correct and I also removed the whole CSRF protection from the login and only used the second cy.request call in my login command and it worked just fine.
Can someone help me out with this?
The below code worked for me,
PS: Only for UI based login.
before(() => {
cy.visit("/");
cy.get(/*<get the webelement for csrf token>*/).invoke('attr', 'value').then(($value) => {
cy.setCookie('csrftoken', $value);
});
});
beforeEach(() => {
Cypress.Cookies.preserveOnce('csrftoken');
});
Refer to the CSRF Tokens demo in the Cypress Recipes repo.
https://github.com/cypress-io/cypress-example-recipes/tree/master/examples/logging-in__csrf-tokens
I had exactly the same problem: The form would just reload without any error.
Turns out for me this happened because php sessions in Symfony where not working with APP_ENV=test and therefore the csrf token would change on every request ;-) I had to switch to dev or prod and then it worked just fine.
I discovered this by testing if the csfr token would be the same between reloads:
describe('Check csrf', () => {
it('Grabs Token and reloads', () => {
// get csrf token and output to command log
cy.request('/login')
.its('body')
.then((body) => {
const $html = Cypress.$(body)
const csrf = $html.find('input[name=_csrf_token]').val()
cy.log(csrf)
})
// do the same again
cy.request('/login')
.its('body')
.then((body) => {
const $html = Cypress.$(body)
const csrf = $html.find('input[name=_csrf_token]').val()
cy.log(csrf)
})
})
})

Resources