-
-
Save csuzw/845b589549b61d3a5fe18e49592e166f to your computer and use it in GitHub Desktop.
// This goes in cypress/plugins/index.js | |
const AzureAdSingleSignOn = require('./azure-ad-sso/plugin').AzureAdSingleSignOn | |
module.exports = (on, config) => { | |
on('task', {AzureAdSingleSignOn:AzureAdSingleSignOn}) | |
} |
// This is an example of how you might use the plugin in your tests | |
describe('My spec', function() { | |
Cypress.Commands.add('setCookies', function () { | |
const options = { | |
username: Cypress.env('username'), | |
password: Cypress.env('password'), | |
loginUrl: Cypress.env('appUrl'), | |
postLoginSelector: '#myselector', | |
headless: true, | |
logs: false | |
} | |
cy.task('AzureAdSingleSignOn', options).then(result => { | |
cy.clearCookies() | |
result.cookies.forEach(cookie => { | |
cy.setCookie(cookie.name, cookie.value, { | |
domain: cookie.domain, | |
expiry: cookie.expires, | |
httpOnly: cookie.httpOnly, | |
path: cookie.path, | |
secure: cookie.secure | |
}) | |
Cypress.Cookies.preserveOnce(cookie.name) | |
}) | |
}) | |
}) | |
before(function() { | |
cy.setCookies(); | |
}) | |
it('Visits the site as logged in user', function() { | |
cy.visit(Cypress.env('appUrl')); | |
cy.contains(`Hello, ${Cypress.env('username')}!`) | |
}) | |
}) |
// I put this in cypress/plugins/azure-ad-sso directory | |
'use strict' | |
const puppeteer = require('puppeteer') | |
/** | |
* | |
* @param {options.username} string username | |
* @param {options.password} string password | |
* @param {options.loginUrl} string password | |
* @param {options.postLoginSelector} string a selector on the app's post-login return page to assert that login is successful | |
* @param {options.headless} boolean launch puppeteer in headless more or not | |
* @param {options.logs} boolean whether to log cookies and other metadata to console | |
* @param {options.getAllBrowserCookies} boolean whether to get all browser cookies instead of just for the loginUrl | |
*/ | |
module.exports.AzureAdSingleSignOn = async function AzureAdSingleSignOn(options = {}) { | |
validateOptions(options) | |
const browser = await puppeteer.launch({ headless: !!options.headless }) | |
const page = await browser.newPage() | |
await page.goto(options.loginUrl) | |
await typeUsername({ page, options }) | |
await typePassword({ page, options }) | |
const cookies = await getCookies({ page, options }) | |
await finalizeSession({ page, browser, options }) | |
return { | |
cookies | |
} | |
} | |
function validateOptions(options) { | |
if (!options.username || !options.password) { | |
throw new Error('Username or Password missing for login') | |
} | |
if (!options.loginUrl) { | |
throw new Error('Login Url missing') | |
} | |
if (!options.postLoginSelector) { | |
throw new Error('Post login selector missing') | |
} | |
} | |
async function typeUsername({ page, options } = {}) { | |
await page.waitForSelector('input[name=loginfmt]:not(.moveOffScreen)', { visible: true, delay: 10000 }) | |
await page.type('input[name=loginfmt]', options.username, { delay: 50 }) | |
await page.click('input[type=submit]') | |
} | |
async function typePassword({ page, options } = {}) { | |
await page.waitForSelector('input[name=Password]:not(.moveOffScreen),input[name=passwd]:not(.moveOffScreen)', { visible: true, delay: 10000 }) | |
await page.type('input[name=passwd]', options.password, { delay: 50 }) | |
await page.click('input[type=submit]') | |
} | |
async function getCookies({ page, options } = {}) { | |
await page.waitForSelector(options.postLoginSelector, { visible: true, delay: 10000 }) | |
const cookies = options.getAllBrowserCookies | |
? await getCookiesForAllDomains(page) | |
: await page.cookies(options.loginUrl) | |
if (options.logs) { | |
console.log(cookies) | |
} | |
return cookies | |
} | |
async function getCookiesForAllDomains(page) { | |
const cookies = await page._client.send('Network.getAllCookies', {}) | |
return cookies.cookies | |
} | |
async function finalizeSession({ page, browser, options } = {}) { | |
await browser.close() | |
} |
Thanks for your prompt response!
Is there a way to get all the keys and values from local storage instead of the cookies? I'm getting "localStorage is not defined"
The issue I am facing now is that I am getting a 302 in Cypress when trying to run this. Puppeteer fills out the Azure information, and successfully logs in, but when trying to open the desired page in Cypress, I get the 302. Has anybody had issues with this? @csuzw?
I am also facing this issue as @WvdE described. its successfully logged in using puppeteer and giving me cypresserror:cy.task('AzureAdSingleSignOn') timed out after waiting 60000ms. Could you please help
cy.task("azureSingleSignOn", options, { timeout: 200000 }).then(({ cookies }) => {
cy.log(cookies);
console.log(cookies);
cookies.forEach((cookie) => {
if (cookie) {
cy.setCookie(cookie.name, cookie.value, {
domain: cookie.domain,
expiry: cookie.expires,
httpOnly: cookie.httpOnly,
path: cookie.path,
secure: cookie.secure,
sameSite: "lax",
});
Cypress.Cookies.defaults({ preserve: cookie.name });
}
});
Why after set cookies and preserve that, When I tried cy.visit("/") its again going to sso azure login page? When I debug I saw cookies are remove automatically. What is the issue?
Able to run. connect puppeteer method. Launch method giving cookies but cypress remove those cookies on cy.visit("/").
const browser = await puppeteer.connect({
browserURL: `http://localhost:${debuggingPort}`,
defaultViewport: null,
});
Any updates on how this works with the new cy.session()
? I'm struggling to get it working because Cypress.Cookies.defaults
got removed.
Setting
getAllBrowserCookies
to true fixed it! @csuzw