-
-
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() | |
| } |
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.


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"