perfrunner-core
Version:
Automated UI performance test tool to measure performance changes for the web apps and sites
112 lines (111 loc) • 5.3 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractPerformanceMetrics = void 0;
const trace_1 = require("./trace");
const performance_observers_1 = require("./performance-observers");
const logger_1 = require("../logger");
const utils_1 = require("../utils");
function extractPageMetrics(page) {
return __awaiter(this, void 0, void 0, function* () {
(0, logger_1.debug)('extracting page metrics');
return yield page.metrics();
});
}
function extractObservablePerformanceEntries(page) {
return __awaiter(this, void 0, void 0, function* () {
(0, logger_1.debug)('extracting observable performance entries');
const rawMetrics = yield page.evaluate(function serializeObservableEntries() {
var _a, _b;
const data = (_b = (_a = window._cpo) === null || _a === void 0 ? void 0 : _a.getEntries()) !== null && _b !== void 0 ? _b : [];
// don't try to move it anywehre: Evaluation failed: ReferenceError: safeSerializer is not defined
function safeSerializer() {
const seen = new WeakSet();
return function serializer(key, value) {
var _a;
if (key === 'element') {
// there is a chance that element will be not accessible due to the security reasons (IFrame). So we avoid serializtion of such.
return (_a = value === null || value === void 0 ? void 0 : value.toString()) !== null && _a !== void 0 ? _a : '';
}
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
}
return JSON.stringify(data, safeSerializer());
});
return JSON.parse(rawMetrics);
});
}
function extractPerformanceEntries(page) {
return __awaiter(this, void 0, void 0, function* () {
const rawMetrics = yield page.evaluate(() => JSON.stringify(performance.getEntries()));
return JSON.parse(rawMetrics);
});
}
function normalizedPerformanceEntries(performanceEntries) {
const defaultEntries = [];
const lcpEntries = [];
performanceEntries.forEach((p) => {
if (p.entryType === performance_observers_1.LARGEST_CONTENTFUL_PAINT) {
lcpEntries.push(p);
return;
}
defaultEntries.push(p);
});
const [lastLcpEvent] = (0, utils_1.orderByDescending)(lcpEntries, (x) => x.renderTime || x.loadTime || 0);
const result = [...defaultEntries];
if (lastLcpEvent) {
result.push(lastLcpEvent);
}
return result;
}
function updateMissingData(entries, { traceEvents }) {
const traceSubset = (0, trace_1.subsetTrace)(traceEvents);
entries.forEach((entry) => {
var _a, _b;
if (entry.entryType !== 'resource') {
return;
}
const { finish, receiveResponse } = (0, trace_1.extractResourceData)(entry.name, traceSubset);
const mimeType = (_a = receiveResponse === null || receiveResponse === void 0 ? void 0 : receiveResponse.args.data.mimeType) !== null && _a !== void 0 ? _a : 'unknown';
if (!entry.encodedBodySize) {
entry.encodedBodySize = (finish === null || finish === void 0 ? void 0 : finish.args.data.encodedDataLength) || 0;
}
if (!((_b = entry.extension) === null || _b === void 0 ? void 0 : _b.mimeType)) {
if (entry.extension) {
entry.extension.mimeType = mimeType;
}
else {
entry.extension = { mimeType };
}
}
});
return entries;
}
function extractPerformanceMetrics(page, trace) {
return __awaiter(this, void 0, void 0, function* () {
const metrics = yield extractPageMetrics(page);
const observables = yield extractObservablePerformanceEntries(page);
const performanceEntries = yield extractPerformanceEntries(page);
const normalizedEntries = normalizedPerformanceEntries([...performanceEntries, ...observables]);
const extendedEntries = updateMissingData(normalizedEntries, trace);
return {
metrics,
performanceEntries: extendedEntries,
};
});
}
exports.extractPerformanceMetrics = extractPerformanceMetrics;