#
Cas d'usages et configurations avancées
#
Audit d'un site nécessitant un cookie
Obligation de créer cookie pour fermer une popin, par exemple.
#
Utilisation du fichier extra-header.json
{ "Cookie": "monster=blue", "x-men": "wolverine" }
#
Utilisation du fichier input-file.json
{
"extra-header": {
"Cookie": "monster=blue",
"x-men": "wolverine"
}
// ...
}
#
Audit d'un site à accès sécurisé
#
En mode simple (liste d'URLs)
npx lighthouse-plugin-ecoindex collect -u https://greenit.eco/ -u https://greenit.eco/wp-login.php/ -u https://greenit.eco/wp-admin/plugins.php --auth.url %test_url% --auth.user.target '#user_login' --auth.user.value %username_value% --auth.pass.target '#user_pass' --auth.pass.value %password_value% -o html
#
En mode mesure de parcours (avec le fichier de config JSON)
La page d'authentiifcation doit faire partie de la liste de page à mesurer, cela pour chaque parcours dont une partie ou la totalité des pages sont sécurisée.
{
"$schema": "/workspace/docs/static/schema/5.1/schema.json",
"extra-header": {
"Cookie": "monster=blue",
"x-men": "wolverine"
},
"output": ["html", "json", "statement"],
"user-agent": "random",
"output-path": "./reports/multi",
"auth": {
"url": "https://domain.ltd/login/",
"user": {
"target": "#user_login",
"value": "******"
},
"pass": {
"target": "#user_pass",
"value": "*****"
}
},
"courses": [...]
}
// https://pptr.dev/guides/configuration
// https://github.com/GoogleChrome/lighthouse-ci/blob/main/docs/configuration.md#puppeteerscript
/**
* @param {puppeteer.Browser} browser
* @param {{url: string, options: LHCI.CollectCommand.Options}} context
*/
module.exports = async (browser, context) => {
// launch browser for LHCI
var page = await browser.newPage(context.options)
// To be set by env vars
const authenticate = {
loginPage: `https://greenit.eco/wp-login.php/`,
loginField: '#user_login',
loginValue: process.env.LOGIN_VALUE || '********',
passField: '#user_pass',
passValue: process.env.PASS_VALUE || '********',
}
// Test if current page is the login URL page
if (context.url === authenticate.loginPage) {
console.log(`Authenticate on`, authenticate.loginPage)
connect(page, browser, authenticate)
} else {
const session = await page.target().createCDPSession()
try {
await page.goto(context.url, {
waitUntil: 'networkidle0',
timeout: 10000, // change timeout to 10s for crashing tests faster.
})
} catch (error) {
console.error('Error getting page:', error.message)
console.error('Retry...')
await page.goto(context.url)
}
await startEcoindexPageMesure(page, session)
await endEcoindexPageMesure()
// close session for next run
await page.close()
}
}
async function connect(page, browser, authenticate) {
page = await browser.newPage()
await page.goto(authenticate.loginPage)
await page.type(authenticate.loginField, authenticate.loginValue)
await page.type(authenticate.passField, authenticate.passValue)
await page.click('[type="submit"]')
try {
await page.waitForNavigation()
// close session for next run
await page.close()
console.log(`Authenticated!`)
} catch (error) {
throw new Error(`Connection failed!`)
}
}
async function startEcoindexPageMesure(page, session) {
page.setViewport({
width: 1920,
height: 1080,
})
await new Promise(r => setTimeout(r, 3 * 1000))
const dimensions = await page.evaluate(() => {
var body = document.body,
html = document.documentElement
var height = Math.max(
body.scrollHeight,
body.offsetHeight,
html.clientHeight,
html.scrollHeight,
html.offsetHeight,
)
return {
width: document.documentElement.clientWidth,
height: height,
deviceScaleFactor: window.devicePixelRatio,
}
})
// console.log('dimensions', dimensions)
// We need the ability to scroll like a user. There's not a direct puppeteer function for this, but we can use the DevTools Protocol and issue a Input.synthesizeScrollGesture event, which has convenient parameters like repetitions and delay to somewhat simulate a more natural scrolling gesture.
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-synthesizeScrollGesture
await session.send('Input.synthesizeScrollGesture', {
x: 100,
y: 600,
yDistance: -dimensions.height,
speed: 1000,
})
}
/**
* End Ecoindex flow. Wait 3s.
*/
async function endEcoindexPageMesure() {
await new Promise(r => setTimeout(r, 3 * 1000))
}
#
Utilisation d'un fichier de script Puppeteer custom
L'utilisation d'un fichier de script Puppeteer custom est recommandée pour les audits de sites nécessitant une authentification complexe.
Points d'attention:
- Due à une limitation de Lighthouse, on ne peut pas mesurer plusieurs fois la même url. Le workaround est d'appeler les urls avec des faux paramètres de navigation, ex. https://greenit.eco/?test=123 pour les différencier.
- Les scénarios complexes avec des pages d'authentifications et des soumissions de formulaires, des pages de redirection, etc. seront mal mesurées (à cause des navigations entre les pages). Il faut donc être vigilant sur les pages à mesurer et ne pas hésiter à ajouter plusieurs pages dans le fichier de configuration en utilisant des faux paramètres de navigation (ex. https://greenit.eco/?test=123).
- Hors des pages d'authentification, les pages doivent être utilisée avec les scénarios de mesure de parcours standards
startEcoindexPageMesure(page, session)
etendEcoindexPageMesure(flow)
.
#
Utilisation en ligne de commande
npx lighthouse-plugin-ecoindex collect -u https://greenit.eco/ -u https://greenit.eco/wp-login.php/ -u https://greenit.eco/wp-admin/plugins.php --puppeteer-script ./puppeteer-script.mjs
import puppeteer from 'puppeteer-core'
/**
* Init Ecoindex flow. Wait 3s, then navigate to bottom of page.
* @param {puppeteer.Page} page
* @param {puppeteer.CDPSession} session
*/
async function startEcoindexPageMesure(page, session) {
page.setViewport({
width: 1920,
height: 1080,
})
await new Promise(r => setTimeout(r, 3 * 1000))
const dimensions = await page.evaluate(() => {
const body = document.body,
html = document.documentElement
const height = Math.max(
body.scrollHeight,
body.offsetHeight,
html.clientHeight,
html.scrollHeight,
html.offsetHeight,
)
return {
width: document.documentElement.clientWidth,
height: height,
deviceScaleFactor: window.devicePixelRatio,
}
})
// console.log('dimensions', dimensions)
// We need the ability to scroll like a user. There's not a direct puppeteer function for this, but we can use the DevTools Protocol and issue a Input.synthesizeScrollGesture event, which has convenient parameters like repetitions and delay to somewhat simulate a more natural scrolling gesture.
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-synthesizeScrollGesture
await session.send('Input.synthesizeScrollGesture', {
x: 100,
y: 600,
yDistance: -dimensions.height,
speed: 1000,
})
}
/**
* End Ecoindex flow. Wait 3s.
* @param {LH.UserFlow} flow
* @param {boolean} [snapshotEnabled=false]
*/
async function endEcoindexPageMesure(flow, snapshotEnabled = false) {
await new Promise(r => setTimeout(r, 3 * 1000))
if (snapshotEnabled) await flow.snapshot()
}
export default async function (options) {
const { page, session, flow, position, urls } = options
console.log('position', position)
console.log('urls', urls)
await startEcoindexPageMesure(page, session)
await endEcoindexPageMesure(flow)
}
#
Utilisation avec un fichier de configuration input-file.json
{
// ...
"puppeteer-script": "./puppeteer-script.mjs"
// ...
}
import puppeteer from 'puppeteer-core'
/**
* Init Ecoindex flow. Wait 3s, then navigate to bottom of page.
* @param {puppeteer.Page} page
* @param {puppeteer.CDPSession} session
*/
async function startEcoindexPageMesure(page, session) {
page.setViewport({
width: 1920,
height: 1080,
})
await new Promise(r => setTimeout(r, 3 * 1000))
const dimensions = await page.evaluate(() => {
const body = document.body,
html = document.documentElement
const height = Math.max(
body.scrollHeight,
body.offsetHeight,
html.clientHeight,
html.scrollHeight,
html.offsetHeight,
)
return {
width: document.documentElement.clientWidth,
height: height,
deviceScaleFactor: window.devicePixelRatio,
}
})
// console.log('dimensions', dimensions)
// We need the ability to scroll like a user. There's not a direct puppeteer function for this, but we can use the DevTools Protocol and issue a Input.synthesizeScrollGesture event, which has convenient parameters like repetitions and delay to somewhat simulate a more natural scrolling gesture.
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-synthesizeScrollGesture
await session.send('Input.synthesizeScrollGesture', {
x: 100,
y: 600,
yDistance: -dimensions.height,
speed: 1000,
})
}
/**
* End Ecoindex flow. Wait 3s.
* @param {LH.UserFlow} flow
* @param {boolean} [snapshotEnabled=false]
*/
async function endEcoindexPageMesure(flow, snapshotEnabled = false) {
await new Promise(r => setTimeout(r, 3 * 1000))
if (snapshotEnabled) await flow.snapshot()
}
export default async function (options) {
const { page, session, flow, position, urls } = options
console.log('position', position)
console.log('urls', urls)
await startEcoindexPageMesure(page, session)
await endEcoindexPageMesure(flow)
}