ประภาคารและนักเชิดหุ่น ตรวจสอบหน้าต้องมีการรับรองความถูกต้อง

ฉันมีเว็บแอป SPA ซึ่งสร้างโดย vue หน้าดังกล่าวได้รับการปกป้องโดยหน้าเข้าสู่ระบบ (จริง ๆ แล้วเป็นเราเตอร์ vue)

หลังจากเข้าสู่ระบบ โทเค็นจะถูกเก็บไว้ใน sessionStorage จากนั้นข้ามไปที่หน้าแรก (เราเตอร์ vue อื่น)

ฉันต้องการใช้ lighthouse เพื่อตรวจสอบหน้าแรก แต่ไม่สามารถเข้าสู่ระบบด้วย puppeteer ได้ รหัสของฉัน:

'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
    };
}

ฉันต้องการใช้ puppeteer เพื่อเข้าสู่ระบบก่อน ในแท็บแยก จากนั้นจึงขยายโทเค็นจาก sessionStorage และเมื่อถึงจุดหนึ่งเมื่อประภาคารเริ่มโหลด url (แท็บอื่น) ให้ฉีดโทเค็นไปที่ sessionStorage แต่ล้มเหลวด้วย :execution context was destroyed โปรดช่วยด้วยใน targetchange Listener

นอกจากนี้ ฉันอยากรู้ว่าฉันควรยืนยันที่จะตรวจสอบหน้าแรกหรือไม่ เนื่องจากเป็น vue SPA? เนื่องจากเนื้อหาส่วนใหญ่โหลดอยู่ในหน้าเข้าสู่ระบบแล้ว


person WestFarmer    schedule 03.04.2020    source แหล่งที่มา


คำตอบ (2)


ฉันเพิ่งเริ่มทำงานกับการทดสอบประสิทธิภาพ ฉันมีกรณีการใช้งานที่แน่นอน วิธีแก้ปัญหาอย่างหนึ่งคือทำการเปลี่ยนแปลงในไฟล์ - lighthouse › lighthouse-core › รวบรวม › การเชื่อมต่อ › CriConnections › cri.js


ที่นี่ ในฟังก์ชัน 'เชื่อมต่อ' ใต้คลาส 'CriConnection' แสดงความคิดเห็นเกี่ยวกับการสร้างแท็บใหม่

connect() {
// return this._runJsonCommand('new')
//   .then(response => this._connectToSocket(/** @type {LH.DevToolsJsonTarget} */(response)))
//   .catch(_ => {
    // Compat: headless didn't support `/json/new` before m59. (#970, crbug.com/699392)
    // If no support, we fallback and reuse an existing open tab
    
    log.warn('CriConnection', 'Cannot create new tab; reusing open tab.');
    return this._runJsonCommand('list').then(tabs => {
      if (!Array.isArray(tabs) || tabs.length === 0) {
        return Promise.reject(new Error('Cannot create new tab, and no tabs already open.'));
      }
      const firstTab = tabs[0];
      // first, we activate it to a foreground tab, then we connect
      return this._runJsonCommand(`activate/${firstTab.id}`)
          .then(() => this._connectToSocket(firstTab));
    });
  // });}

แม้ว่า โปรดทราบว่านี่อาจไม่ใช่แนวทางปฏิบัติที่ดีที่สุด แต่นี่คือทั้งหมดที่ฉันมีจนถึงตอนนี้ ฉันกำลังมองหาวิธีแก้ปัญหาที่ดีกว่านี้อย่างจริงจัง จะอัปเดตถ้าฉันพบ!

person Parbinder Singh    schedule 28.12.2020

คุณสามารถใช้ตัวรวบรวมแบบกำหนดเองเพื่อฉีดโทเค็นไปยังที่เก็บข้อมูลเซสชัน: `

    async function createSession(token) {
  if (sessionStorage) {
    sessionStorage.setItem("jwt_token", token);
  }
}

class SessionGatherer extends Gatherer {
  constructor() {
    super();
  }

  async beforePass(options) {
    // if (!credentials[0] == "Login page") {
    const TOKEN = await new TokenService().fetchToken();
    const driver = options.driver;
    return driver.evaluateScriptOnNewDocument(
      `(${createSession.toString()})('${TOKEN}')`
    );
  }
}

จำเป็นต้องเพิ่มตัวรวบรวมแบบกำหนดเองในการกำหนดค่า lighthouse:

   const lighthouse_config = {
  extends: "lighthouse:default",
  settings: {
    formFactor: "desktop",
    screenEmulation: {
      mobile: false,
      width: 1024,
      height: 768,
      deviceScaleFactor: 1,
      disabled: false,
    },
  },
  passes: [
    {
      passName: "defaultPass",
      gatherers: [`session-gatherer`],
    },
  ]}
person Parbinder Singh    schedule 21.01.2021