PromucFlow_constructor/app/client/perf/src/perf.js

192 lines
5.6 KiB
JavaScript
Raw Normal View History

const Tracelib = require("tracelib");
const puppeteer = require("puppeteer");
var sanitize = require("sanitize-filename");
const fs = require("fs");
const path = require("path");
const {
delay,
login,
getFormattedTime,
sortObjectKeys,
} = require("./utils/utils");
const selectors = {
appMoreIcon: "span.t--options-icon",
orgImportAppOption: '[data-cy*="t--org-import-app"]',
fileInput: "#fileInput",
importButton: '[data-cy*="t--org-import-app-button"]',
createNewApp: ".createnew",
};
module.exports = class Perf {
constructor(launchOptions = {}) {
this.launchOptions = {
defaultViewport: null,
args: ["--window-size=1920,1080"],
ignoreHTTPSErrors: true, // @todo Remove it after initial testing
...launchOptions,
};
if (process.env.PERF_TEST_ENV === "dev") {
this.launchOptions.executablePath =
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
this.launchOptions.devtools = true;
this.launchOptions.headless = false;
}
this.traces = [];
this.currentTrace = null;
this.browser = null;
// Initial setup
this.currentTestFile = process.argv[1]
.split("/")
.pop()
.replace(".perf.js", "");
global.APP_ROOT = path.join(__dirname, ".."); //Going back one level from src folder to /perf
process.on("unhandledRejection", async (reason, p) => {
console.error("Unhandled Rejection at: Promise", p, "reason:", reason);
const fileName = sanitize(
`${this.currentTestFile}__${this.currentTrace}`,
);
const screenshotPath = `${APP_ROOT}/traces/reports/${fileName}-${getFormattedTime()}.png`;
await this.page.screenshot({
path: screenshotPath,
});
if (this.currentTrace) {
await this.stopTrace();
}
this.browser.close();
});
}
/**
* Launches the browser and, gives you the page
*/
launch = async () => {
this.browser = await puppeteer.launch(this.launchOptions);
const pages_ = await this.browser.pages();
this.page = pages_[0];
await this._login();
};
_login = async () => {
await login(this.page);
await delay(2000, "after login");
};
startTrace = async (action = "foo") => {
if (this.currentTrace) {
console.warn("Trace progress. You can run only one trace at a time");
return;
}
this.currentTrace = action;
await delay(3000, `before starting trace ${action}`);
const path = `${APP_ROOT}/traces/${action}-${getFormattedTime()}-chrome-profile.json`;
await this.page.tracing.start({
path: path,
screenshots: true,
});
this.traces.push({ action, path });
};
stopTrace = async () => {
this.currentTrace = null;
await delay(3000, "before stopping the trace");
await this.page.tracing.stop();
};
getPage = () => {
if (this.page) return this.page;
throw Error("Can't find the page, please call launch method.");
};
loadDSL = async (dsl) => {
const selector = selectors.createNewApp;
await this.page.waitForSelector(selector);
await this.page.click(selector);
// We goto the newly created app.
// Lets update the page
await this.page.waitForNavigation();
const currentUrl = this.page.url();
const pageIdRegex = /pages(.*)/;
const match = pageIdRegex.exec(currentUrl);
const pageId = match[1].split("/")[1];
await this.page.evaluate(
async ({ pageId, dsl }) => {
const layoutId = await fetch(`/api/v1/pages/${pageId}`)
.then((response) => response.json())
.then((data) => data.data.layouts[0].id);
const pageSaveUrl = "/api/v1/layouts/" + layoutId + "/pages/" + pageId;
await fetch(pageSaveUrl, {
headers: {
accept: "application/json, text/plain, */*",
"content-type": "application/json",
},
referrerPolicy: "strict-origin-when-cross-origin",
body: JSON.stringify(dsl),
method: "PUT",
mode: "cors",
credentials: "include",
})
.then((res) =>
console.log("Save page with new DSL response:", res.json()),
)
.catch((err) => {
console.log("Save page with new DSL error:", err);
});
},
{ pageId, dsl },
);
await this.page.goto(currentUrl.replace("generate-page", ""), {
waitUntil: "networkidle2",
timeout: 60000,
});
};
importApplication = async (jsonPath) => {
await this.page.waitForSelector(selectors.appMoreIcon);
await this.page.click(selectors.appMoreIcon);
await this.page.waitForSelector(selectors.orgImportAppOption);
await this.page.click(selectors.orgImportAppOption);
const elementHandle = await this.page.$(selectors.fileInput);
await elementHandle.uploadFile(jsonPath);
await this.page.click(selectors.importButton);
await this.page.waitForNavigation();
await this.page.reload();
};
generateReport = async () => {
const report = {};
this.traces.forEach(({ path, action }) => {
report[action] = {};
const trace = require(path);
const tasks = new Tracelib.default(trace.traceEvents);
report[action].path = path;
report[action].summary = sortObjectKeys(tasks.getSummary());
report[action].warnings = sortObjectKeys(tasks.getWarningCounts());
});
await fs.writeFile(
`${APP_ROOT}/traces/reports/${getFormattedTime()}.json`,
JSON.stringify(report, "", 4),
(err) => {
if (err) {
console.log("Error writing file", err);
} else {
console.log("Successfully wrote report");
}
},
);
};
close = async () => {
this.browser.close();
};
};