From 6a57ea4f6a81022aaec4a07d4d0c53a49cf90299 Mon Sep 17 00:00:00 2001 From: nhthinh-axonivy Date: Fri, 27 Dec 2024 17:42:50 +0700 Subject: [PATCH] feature/IVYPORTAL-17377-Create-pipeline-to-run-Lighthouse-report --- .../lighthouse/puppeteer-script.js | 81 ---------- .../lighthouse/puppeteer-script.mjs | 145 +++++++----------- 2 files changed, 52 insertions(+), 174 deletions(-) delete mode 100644 AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.js diff --git a/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.js b/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.js deleted file mode 100644 index e6ae0d6638..0000000000 --- a/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.js +++ /dev/null @@ -1,81 +0,0 @@ -import fs from "fs"; -import path from "path"; -import puppeteer from "puppeteer"; -import { fileURLToPath } from "url"; -import { dirname } from "path"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -// Add type: module to package.json -const packageJson = { - type: "module", -}; - -(async () => { - try { - // Dynamically import lighthouse - const lighthouse = (await import("lighthouse")).default; - - // Read user credentials - const csvFilePath = path.join(__dirname, "../jmeter/data/users_local.csv"); - const users = fs - .readFileSync(csvFilePath, "utf-8") - .split("\n") - .filter(Boolean) - .map((line) => { - const [username, password] = line.trim().split(","); - return { username, password }; - }); - - // Launch browser - const browser = await puppeteer.launch({ - headless: "new", - args: [ - "--no-sandbox", - "--disable-setuid-sandbox", - "--disable-gpu", - "--disable-dev-shm-usage", - ], - }); - - const page = await browser.newPage(); - await page.setViewport({ width: 1920, height: 1080 }); - - // Login process - const user = users[0]; - await page.goto("http://localhost:8080/Portal", { - waitUntil: "networkidle0", - }); - await page.waitForSelector("#username"); - await page.type("#username", user.username); - await page.type("#password", user.password); - await page.click('button[type="submit"]'); - await page.waitForNavigation({ waitUntil: "networkidle0" }); - - // Run Lighthouse - const { lhr } = await lighthouse(page.url(), { - port: new URL(browser.wsEndpoint()).port, - output: ["json", "html"], - logLevel: "info", - onlyCategories: ["performance", "accessibility", "best-practices", "seo"], - }); - - // Ensure directory exists - if (!fs.existsSync("lighthouse-reports")) { - fs.mkdirSync("lighthouse-reports"); - } - - // Save reports - fs.writeFileSync("lighthouse-reports/report.html", lhr.report[1]); - fs.writeFileSync( - "lighthouse-reports/report.json", - JSON.stringify(lhr, null, 2) - ); - - await browser.close(); - } catch (error) { - console.error("Error:", error); - process.exit(1); - } -})(); diff --git a/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.mjs b/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.mjs index 9f88b8c545..86e808ba62 100644 --- a/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.mjs +++ b/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.mjs @@ -8,127 +8,86 @@ import { dirname } from "path"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); +const debugLog = (msg) => console.log(`[Debug] ${msg}`); + (async () => { + let browser; try { - const formData = { - "javax.faces.partial.ajax": "true", - "javax.faces.source": "login-form:login-command", - "javax.faces.partial.execute": "@all", - "javax.faces.partial.render": "login:login-form", - "login:login-form:username": "admin", // Replace with actual username - "login:login-form:password": "admin", // Replace with actual password - "javax.faces.ViewState": "dynamic-view-state", // Fetch dynamically if required - "login:login-form_SUBMIT": "1", - }; + // Health check + debugLog("Checking server status..."); + const healthCheck = await fetch("http://localhost:8080/portal/health"); + if (!healthCheck.ok) { + throw new Error(`Server health check failed: ${healthCheck.status}`); + } + debugLog("Server is healthy"); // Launch browser - const browser = await puppeteer.launch({ + debugLog("Launching browser..."); + browser = await puppeteer.launch({ headless: "new", args: [ "--no-sandbox", "--disable-setuid-sandbox", "--disable-gpu", - "--disable-dev-shm-usage", + "--window-size=1920,1080", ], }); const page = await browser.newPage(); await page.setViewport({ width: 1920, height: 1080 }); + debugLog("Browser launched"); - // Login process - await page.goto( - "http://localhost:8080/Portal/pro/portal/1549F58C18A6C562/DashboardPage.ivp?dashboardId=1", - { - waitUntil: "networkidle0", - } - ); + // Test portal access + const portalUrl = "http://localhost:8080/portal/faces/login.xhtml"; + debugLog(`Navigating to ${portalUrl}`); - await page.evaluate((data) => { - const form = document.createElement("form"); - form.method = "POST"; - form.action = location.href; // Current page URL + const response = await page.goto(portalUrl, { + waitUntil: ["networkidle0", "domcontentloaded"], + timeout: 60000, + }); - Object.entries(data).forEach(([key, value]) => { - const input = document.createElement("input"); - input.type = "hidden"; - input.name = key; - input.value = value; - form.appendChild(input); - }); + if (!response.ok()) { + throw new Error(`Page load failed: ${response.status()}`); + } + debugLog(`Portal loaded: ${response.status()}`); - document.body.appendChild(form); - form.submit(); - }, formData); + // Login + debugLog("Attempting login..."); + await page.waitForSelector("#username", { visible: true, timeout: 30000 }); + await page.type("#username", "demo"); + await page.type("#password", "demo"); - // Wait for navigation after login - await page.waitForNavigation(); + await Promise.all([ + page.click('button[type="submit"]'), + page.waitForNavigation({ + waitUntil: "networkidle0", + timeout: 30000, + }), + ]); + debugLog("Login successful"); // Run Lighthouse - const runnerResult = await lighthouse(page.url(), { + debugLog("Starting Lighthouse audit..."); + const { lhr } = await lighthouse(page.url(), { port: new URL(browser.wsEndpoint()).port, output: ["html", "json"], logLevel: "info", - onlyCategories: ["performance", "accessibility", "best-practices", "seo"], - formFactor: "desktop", - screenEmulation: { - mobile: false, - width: 1920, - height: 1080, - deviceScaleFactor: 1, - disabled: false, - }, }); // Save reports - try { - const scriptDir = dirname(fileURLToPath(import.meta.url)); - const reportsDir = path.join(scriptDir, "lighthouse-reports"); - - console.log("Script directory:", scriptDir); - console.log("Reports directory:", reportsDir); - - // Ensure reports directory exists - if (!fs.existsSync(reportsDir)) { - fs.mkdirSync(reportsDir, { recursive: true }); - } - - if (runnerResult && runnerResult.report) { - // Get the HTML report (it's the first output format) - const htmlReport = Array.isArray(runnerResult.report) - ? runnerResult.report[0] - : runnerResult.report; - - if (typeof htmlReport === "string") { - // Save HTML report in both locations - const htmlPaths = [ - path.join(scriptDir, "lighthouse-report.html"), - path.join(reportsDir, "lighthouse-report.html"), - ]; - - htmlPaths.forEach((htmlPath) => { - fs.writeFileSync(htmlPath, htmlReport); - console.log("HTML report saved to:", htmlPath); - }); - } else { - throw new Error("HTML report is not a string"); - } - - // Save JSON report - const jsonPath = path.join(reportsDir, "report.json"); - fs.writeFileSync(jsonPath, JSON.stringify(runnerResult.lhr, null, 2)); - console.log("JSON report saved to:", jsonPath); - } else { - console.error("Runner result:", runnerResult); - throw new Error("No valid report data in runner result"); - } - } catch (error) { - console.error("Error saving reports:", error); - throw error; - } - - await browser.close(); + fs.writeFileSync("lighthouse-report.html", lhr.report[0]); + fs.writeFileSync( + "lighthouse-reports/report.json", + JSON.stringify(lhr, null, 2) + ); + debugLog("Reports saved"); } catch (error) { - console.error("Error:", error); + debugLog(`Error: ${error.message}`); + console.error(error); process.exit(1); + } finally { + if (browser) { + await browser.close(); + } } })();