I have a SPA web app, which is built by vue. the page is protected by a login page(a vue router actually),
after login, a token is stored in sessionStorage, then jump to home page(another vue router.)
I want to use lighthouse to audit the home page, but can’t make the login with puppeteer. my code:
'use strict';
const puppeteer = require('puppeteer-core')
const lighthouse = require('lighthouse')
const http = require('http')
const PORT = 8041;
const opts = {
hostname: 'x.x.x.x',
port: 9876,
path: '/lighthouse/scores',
method: 'POST',
timeout: 5000,
headers : {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
}
}
var session;
// 登录
async function login(broswer, origin){
const loginPage = (await broswer.pages())[0];
await loginPage.goto(origin);
await loginPage.waitForSelector('#pane-pwd > form > div:nth-child(1) > div > div > input', {visible: true});
const userInput = await loginPage.$('#pane-pwd > form > div:nth-child(1) > div > div > input');
await userInput.type('admin');
const pswdInput = await loginPage.$('#pane-pwd > form > div:nth-child(2) > div > div > input');
await pswdInput.type('123456');
const loginButton = await loginPage.$('#app > div > div.main > div.tabs > div.bt-wrap > button');
await loginButton.click();
await loginPage.waitForSelector('.home');
const states = await loginPage.evaluate(() => {
//alert(sessionStorage.getItem('default'));
return JSON.stringify(sessionStorage);
})
session = JSON.parse(states);
return session;
}
// 上传lighthouse结果
function uploadReport(scores){
console.log('--------------------- uploading lighthouse report --------------------- ');
const req = http.request(opts, res => {
console.log(`Update : statusCode: ${res.statusCode}`)
if(res.statusCode != '204'){
console.error(res.statusMessage)
}else{
}
});
req.on('error', error => {
console.error(error)
});
req.write(scores);
req.end();
}
async function main(){
const broswer = await puppeteer.launch({
args : [`--remote-debugging-port=${PORT}`],
headless : false,
defaultViewport : null,
executablePath : '/usr/bin/google-chrome-stable'
});
const session = await login(broswer, 'http://x.x.x.x/');
console.log(session);
broswer.once('targetchanged', async target => {
console.log('------- target changed -------');
const page = await target.page();
await page.waitForNavigation();
page.evaluate((session) => {
console.log('------- copy session state -------')
sessionStorage.setItem('___un__solvable___secrets__', session['___un__solvable___secrets__']);
sessionStorage.setItem('default', session['default']);
}, session);
});
const result = await lighthouse('http://x.x.x.x/#/admin/home', {port: PORT, disableStorageReset : true, disableDeviceEmulation: true, emulatedFormFactor : 'desktop'})
const scores = {
project : 'P364',
url : '/',
performance : result.lhr.categories.performance.score,
accessibility : result.lhr.categories.accessibility.score,
bestPractice : result.lhr.categories['best-practices'].score,
pwa : result.lhr.categories.pwa.score,
seo : result.lhr.categories.seo.score,
}
console.log(scores);
uploadReport(JSON.stringify(scores));
//await broswer.close();
}
if(require.main === module){
main();
}else{
module.exports = {
login
};
}
I want to use puppeteer to login first, in a seprate tab, then extact token from sessionStorage, and at some point when lighthouse begin to load the url(another tab), inject the token to sessionStorage. but failed with :execution context was destroyed
, in the targetchange listener, please help.
besides, I want to know shoud I insist to audit the home page, as it’s a vue SPA? as most assets already loaded in login page.
2
Answers
I’ve recently started working on performance tests. I have exact use case. One workaround is to make a change in the file – lighthouse > lighthouse-core > gather > connections > CriConnections > cri.js.
Here, in function ‘connect’ under class ‘CriConnection’ comment new tab creation.
Although, please note, this might not be a best practice. But this is all I have so far. I’m actively looking for a better solution. Will update, if I find any !
You can use a custom gatherer to inject a token to session storage:
`
Custom gatherer needs to be added to the lighthouse config: