html-report.galen-report.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of galen-core Show documentation
Show all versions of galen-core Show documentation
A library for layout testing of websites
jQuery.fn.centerHorizontally = function () {
this.css("position","absolute");
this.css("top", Math.max(0, $(window).scrollTop() + 80) + "px");
this.css("left", Math.max(0, (($(window).width() - $(this).outerWidth()) / 2) +
$(window).scrollLeft()) + "px");
return this;
}
var _GalenReport = {};
function setHtml(id, html) {
document.getElementById(id).innerHTML = html;
}
function haveSimilarElements(array1, array2) {
return $(array1).filter(array2).length > 0;
}
function createTemplate(templateId) {
var source = document.getElementById(templateId).innerHTML;
return Handlebars.compile(source);
}
function safeHtml(html) {
return new Handlebars.SafeString(html);
}
function hasChildElements(items) {
return items !== null && items !== undefined && Array.isArray(items) && items.length > 0;
}
function onExpandNodeClick() {
var expandLink = this;
var container = $(this).siblings(".expand-container");
container.slideToggle({
duration: "fast",
complete: function () {
if ($(this).is(":visible")) {
$(expandLink).removeClass("collapsed").addClass("expanded");
} else {
$(expandLink).removeClass("expanded").addClass("collapsed");
}
}
});
return false;
}
function ColorPatternPicker() {
this.colors = [
"#B55CFF", "#FF5C98", "#5C9AFF", "#5CE9FF", "#5CFFA3", "#98FF5C", "#FFE95C", "#FFA05C"
];
}
ColorPatternPicker.prototype.index = -1;
ColorPatternPicker.prototype.pickColor = function () {
this.index += 1;
if (this.index >= this.colors.length) {
this.index = 0;
}
return this.colors[this.index];
};
function collectObjectsToHighlight(objects, filterFunction) {
var collected = [],
colorPicker = new ColorPatternPicker();
for (var objectName in objects) {
if (objects.hasOwnProperty(objectName)) {
if (filterFunction(objectName, objects[objectName])) {
var area = objects[objectName].area;
collected.push({
name: objectName,
area: {
left: area[0] - 3,
top: area[1] - 3,
width: area[2],
height: area[3]
},
color: colorPicker.pickColor(),
drawBorder: true,
fillBackground: false
});
}
}
}
return sortByArea(collected);
}
function sortByArea(objects) {
return objects.sort(function (a, b) {
return b.area.width*b.area.height - a.area.width*a.area.height;
});
}
function findScreenSize(objects) {
var maxWidth = 0;
var maxHeight = 0;
for (var objectName in objects) {
if (objectName === "screen") {
return {
width: objects[objectName].area[2],
height: objects[objectName].area[3]
};
} else {
if (maxWidth < objects[objectName].area[2]) {
maxWidth = objects[objectName].area[2];
}
if (maxHeight < objects[objectName].area[3]) {
maxHeight = objects[objectName].area[3];
}
}
}
return {
width: maxWidth,
height: maxHeight
};
}
function findClosestScreenshotData($element) {
var $closest = $element.closest("[data-screenshot]");
if ($closest.length > 0) {
return $closest.attr("data-screenshot");
} else {
return null;
}
}
function onLayoutCheckClick() {
$this = $(this);
var objectNames = $this.attr("data-highlight-objects").split(",");
var checkText = $this.text();
var errorText = $this.next(".layout-check-error-message").find(".layout-check-error-message-text").text();
var layoutId = $this.closest(".layout-report").attr("data-layout-id");
var screenshot = findClosestScreenshotData($this);
if (layoutId !== "" && layoutId >= 0) {
var layout = _GalenReport.layouts[layoutId];
if (layout !== null) {
var objects = collectObjectsToHighlight(layout.objects, function (objectName, object) {
return objectNames.indexOf(objectName) > -1;
});
if (screenshot === null || screenshot === undefined) {
screenshot = _GalenReport.layouts[0].screenshot;
}
showShadow();
showPopup("Loading ...");
loadImage(screenshot, function () {
_GalenReport.showNotification(checkText, errorText);
_GalenReport.showScreenshotWithObjects(screenshot, this.width, this.height, objects);
}, function () {
var screenSize = findScreenSize(layout.objects);
_GalenReport.showNotification(checkText, errorText);
_GalenReport.showScreenshotWithObjects(null, screenSize.width, screenSize.height, objects);
});
} else {
_GalenReport.showErrorNotification("Couldn't find layout data");
}
} else {
_GalenReport.showErrorNotification("Couldn't find layout data");
}
return false;
}
function loadImage(imagePath, callback, errorCallback) {
var img = new Image();
img.onload = function () {
callback(this, this.width, this.height);
};
img.onerror = function() {
errorCallback(this);
};
img.src = imagePath;
}
function onImageComparisonClick() {
var $this = $(this);
var actualImagePath = $this.attr("data-actual-image");
var expectedImagePath = $this.attr("data-expected-image");
var mapImagePath = $this.attr("data-map-image");
showShadow();
showPopup("Loading ...");
var windowWidth = $(window).width();
loadImage(actualImagePath, function (actualImage, actualImageWidth, actualImageHeight) {
loadImage(expectedImagePath, function (expectedImage, expectedImageWidth, expectedImageHeight) {
loadImage(mapImagePath, function (mapImage, mapImageWidth, mapImageHeight) {
var layout = "vertical";
if (windowWidth - actualImageWidth - expectedImageWidth > 100) {
layout = "horizontal";
}
showPopup(_GalenReport.tpl.imageComparison({
actual: actualImagePath,
expected: expectedImagePath,
map: mapImagePath,
layout: layout
}));
});
});
});
return false;
}
function visitEachSpec(sections, callback) {
if (sections !== null && sections !== undefined) {
for (var i = 0; i < sections.length; i++) {
if (sections[i].sections != undefined && sections[i].sections != null) {
visitEachSpec(sections[i].sections, callback);
}
for (var j = 0; j < sections[i].objects.length; j++) {
for (var k = 0; k < sections[i].objects[j].specs.length; k++) {
callback(sections[i].objects[j].specs[k]);
}
}
}
}
}
function rgb2hex(r,g,b){
return "#" +
("0" + r.toString(16)).slice(-2) +
("0" + g.toString(16)).slice(-2) +
("0" + b.toString(16)).slice(-2);
}
function pickHeatColor(value) {
var max = 6;
var _t = Math.min(value/max, 1.0);
if (_t < 0.5) {
var t = _t*2;
var red = Math.min(Math.floor(255.0 * t), 255);
return rgb2hex(red, 255, 0);
} else {
var t = (_t - 0.5) * 2;
var green = Math.min(Math.floor(255.0 * (1.0 - t)), 255);
return rgb2hex(255, green, 0);
}
}
function collectObjectsForHeatmap(layout) {
var objectsHeatMap = {
};
var collected = [];
visitEachSpec(layout.sections, function (spec) {
for (var i = 0; i < spec.highlight.length; i++) {
var name = spec.highlight[i];
if (name != "screen" && name != "self" && name != "viewport" && name != "parent") {
if (objectsHeatMap[name] !== undefined) {
objectsHeatMap[name] += 1;
} else {
objectsHeatMap[name] = 1;
}
}
if (spec.hasOwnProperty("subLayout")) {
var collectedFromSubLayout = collectObjectsForHeatmap(spec.subLayout);
for (var k = 0; k < collectedFromSubLayout.length; k++) {
collected.push(collectedFromSubLayout[k]);
}
}
}
});
for (objectName in objectsHeatMap) {
if (objectsHeatMap.hasOwnProperty(objectName)) {
var count = objectsHeatMap[objectName];
if (layout.objects.hasOwnProperty(objectName)) {
var area = layout.objects[objectName].area;
collected.push({
name: objectName,
area: {
left: area[0],
top: area[1],
width: area[2],
height: area[3]
},
color: pickHeatColor(count),
drawBorder: false,
fillBackground: true
});
}
}
}
return sortByArea(collected);
}
function onLayoutHeatmapClick() {
$this = $(this);
var layoutId = $this.closest(".node-horizontal-menu").attr("data-layout-id");
if (layoutId !== "" && layoutId >= 0) {
var layout = _GalenReport.layouts[layoutId];
if (layout !== null) {
var objects = collectObjectsForHeatmap(layout);
var screenshot = layout.screenshot;
if (screenshot === null || screenshot === undefined) {
screenshot = _GalenReport.layouts[0].screenshot;
}
showShadow();
showPopup("Loading ...");
loadImage(screenshot, function () {
_GalenReport.showScreenshotWithObjects(screenshot, this.width, this.height, objects);
}, function () {
var screenSize = findScreenSize(layout.objects);
_GalenReport.showNotification("Couldn't load screenshot: " + screenshot, "");
_GalenReport.showScreenshotWithObjects(null, screenSize.width, screenSize.height, objects);
});
} else {
_GalenReport.showErrorNotification("Couldn't find layout data");
}
} else {
_GalenReport.showErrorNotification("Couldn't find layout data");
}
return false;
}
function onNodeExtrasClick() {
var html = $(this).next(".node-extras-content").html();
showPopup(html);
return false;
}
function onNotificationCloseClick() {
$(this).closest(".notification").fadeOut("fast");
return false;
}
function hideNotification() {
$(".notification").fadeOut();
}
function showShadow() {
$("#screen-shadow").fadeIn();
}
function hideShadow() {
$("#screen-shadow").fadeOut();
}
function showPopup(html) {
showShadow();
$("#popup .popup-content").html(html);
$("#popup").centerHorizontally().fadeIn('fast');
}
function hidePopup() {
hideShadow();
$("#popup").fadeOut();
}
function onPopupCloseClick() {
hideShadow();
$(this).closest(".popup").fadeOut();
return false;
}
function expandAllNodes() {
$(".expand-container").show();
$("a.expand-link.contains-children-true").removeClass("collapsed").removeClass("expanded").addClass("expanded");
}
function expandErrorNodes() {
collapseAllNodes();
$(".node-status-error, .layout-check-status-error").parents(".expand-container").show();
}
function collapseAllNodes() {
$(".expand-container").hide();
$("a.expand-link.contains-children-true").removeClass("expanded").removeClass("collapsed").addClass("collapsed");
}
function createGalenReport() {
_GalenReport = {
layouts: [],
registerLayout: function (layout) {
var id = this.layouts.push({
objects: layout.objects,
screenshot: layout.screenshot,
sections: layout.sections
}) - 1;
return id;
},
tpl: {
main: createTemplate("report-tpl"),
reportNode: createTemplate("report-node-tpl"),
reportNodeText: createTemplate("report-node-text-tpl"),
layout: createTemplate("report-layout-tpl"),
layoutSection: createTemplate("report-layout-section-tpl"),
layoutObject: createTemplate("report-layout-object-tpl"),
layoutCheck: createTemplate("report-layout-check-tpl"),
sublayout: createTemplate("report-layout-sublayout-tpl"),
screenshotPopup: createTemplate("screenshot-popup-tpl"),
imageComparison: createTemplate("image-comparison-tpl"),
nodeExtras: createTemplate("node-extras-tpl")
},
render: function (id, reportData) {
setHtml(id, this.tpl.main(reportData));
$("a.expand-link.contains-children-true").click(onExpandNodeClick);
$("a.layout-check").click(onLayoutCheckClick);
$("a.image-comparison-link").click(onImageComparisonClick);
$("a.layout-heatmap-link").click(onLayoutHeatmapClick);
$("a.node-extras").click(onNodeExtrasClick);
expandErrorNodes();
},
showNotification: function (summary, message) {
$("#notification .notification-summary").text(summary);
$("#notification .notification-message").text(message);
$("#notification").fadeIn("fast");
},
showErrorNotification: function (summary, message) {
this.showNotification(summary, message);
},
showScreenshotWithObjects: function (screenshotPath, width, height, objects) {
showPopup(_GalenReport.tpl.screenshotPopup({
screenshot: screenshotPath,
objects: objects,
width: width,
height: height
}));
}
};
$(document).keydown(function(e) {
if (e.keyCode == 27) {
hidePopup();
hideNotification();
}
});
$(".notification-close-link").click(onNotificationCloseClick);
$(".popup-close-link").click(onPopupCloseClick);
$("#screen-shadow").click(function () {
hidePopup();
hideNotification();
});
$(".menu-op-expand-all").click(expandAllNodes);
$(".menu-op-collapse-all").click(collapseAllNodes);
$(".menu-op-expand-errors").click(expandErrorNodes);
return _GalenReport;
}
Handlebars.registerHelper("renderNode", function (node) {
if (node !== null && node !== undefined) {
if (node.type === "node") {
return safeHtml(_GalenReport.tpl.reportNode(node));
} else if (node.type === "text") {
return safeHtml(_GalenReport.tpl.reportNodeText(node));
} else if (node.type === "layout") {
if (node.layoutId === undefined || node.layoutId === null) {
node.layoutId = _GalenReport.registerLayout(node);
}
return safeHtml(_GalenReport.tpl.layout(node));
}
}
return "";
});
Handlebars.registerHelper("renderNodeExtras", function (extras) {
if (extras !== null && extras !== undefined) {
return safeHtml(_GalenReport.tpl.nodeExtras(extras));
}
return "";
});
Handlebars.registerHelper('ifCond', function(v1, v2, options) {
if(v1 === v2) {
return options.fn(this);
}
return options.inverse(this);
});
Handlebars.registerHelper("renderLayoutSection", function (section) {
if (section !== null && section !== undefined) {
return safeHtml(_GalenReport.tpl.layoutSection(section));
}
});
Handlebars.registerHelper("renderLayoutObject", function (object) {
if (object !== null && object !== undefined) {
return safeHtml(_GalenReport.tpl.layoutObject(object));
}
});
Handlebars.registerHelper("renderLayoutCheck", function (check) {
if (check !== null && check !== undefined) {
return safeHtml(_GalenReport.tpl.layoutCheck(check));
}
});
Handlebars.registerHelper("renderSublayout", function (sublayout) {
if (sublayout !== null && sublayout !== undefined) {
if (sublayout.layoutId === undefined || sublayout.layoutId === null) {
sublayout.layoutId = _GalenReport.registerLayout(sublayout);
}
return safeHtml(_GalenReport.tpl.sublayout(sublayout));
}
});
Handlebars.registerHelper("hasChildElements", function (items1, items2) {
if (hasChildElements(items1) || hasChildElements(items2)) {
return "true"
}
return "false";
});
Handlebars.registerHelper("formatReportTime", function (time) {
if (time !== null && time !== undefined) {
var date = new Date(time);
var hh = date.getHours();
var mm = date.getMinutes();
var ss = date.getSeconds();
if (hh < 10) {hh = "0"+hh;}
if (mm < 10) {mm = "0"+mm;}
if (ss < 10) {ss = "0"+ss;}
return hh + ":" + mm + ":" + ss;
}
return "";
});
Handlebars.registerHelper("formatGroupsPretty", function (groups) {
if (groups !== null && groups !== undefined) {
var text = "";
for (var i = 0; i < groups.length; i++) {
if (i > 0) {
text += ", ";
}
text = text + '' + groups[i] + '';
}
return safeHtml(text);
}
return "";
});
Handlebars.registerHelper("formatDurationHumanReadable", function (durationInMillis) {
var durationInSeconds = Math.floor(durationInMillis / 1000);
if (durationInSeconds > 0) {
var hours = Math.floor(durationInSeconds / 3600);
var minutes = Math.floor((durationInSeconds - hours * 3600) / 60);
var seconds = Math.floor(durationInSeconds - hours * 3600 - minutes * 60);
var text = "";
if (hours > 0) {
text += hours + "h";
}
if (minutes > 0 || hours > 0) {
if (hours > 0) {
text += " ";
}
text += minutes;
text += "m";
}
if (seconds > 0) {
if (hours > 0 || minutes > 0) {
text += " ";
}
text += seconds;
text += "s";
}
return text;
}
else return "0";
});
function toStringWithLeadingZero(number) {
if (number < 10) {
return "0" + number;
}
return number;
}
Handlebars.registerHelper("formatDateTime", function (time) {
if (time !== null && time !== undefined) {
var d = new Date(time);
var date = toStringWithLeadingZero(d.getDate());
var month = toStringWithLeadingZero(d.getMonth() + 1);
var year = d.getFullYear();
var hh = toStringWithLeadingZero(d.getHours());
var mm = toStringWithLeadingZero(d.getMinutes());
var ss = toStringWithLeadingZero(d.getSeconds());
return date + "-" + month + "-" + year + " " + hh + ":" + mm + ":" + ss;
}
return "";
});
Handlebars.registerHelper("renderProgressBar", function (statistic) {
var total = statistic.passed + statistic.errors + statistic.warnings;
var passedPercent = Math.round(statistic.passed * 100 / total);
var failedPercent = Math.round(statistic.errors * 100 / total);
var warningPercent = Math.round(statistic.warnings * 100 / total);
return new Handlebars.SafeString("
");
});
Handlebars.registerHelper("renderGroupsProgressBar", function (group) {
var total = group.tests;
var passedPercent = Math.round(group.passed * 100 / total);
var failedPercent = Math.round(group.failed * 100 / total);
return new Handlebars.SafeString("
");
});
Handlebars.registerHelper("commaSeparated", function (items) {
if (items !== null && items !== undefined && items.length > 0) {
var text = "";
for (var i = 0; i < items.length; i++) {
if (i > 0) {
text += ",";
}
text += items[i];
}
return text;
}
return "";
});
function createGalenTestOverview() {
$.extend($.tablesorter.themes.jui, {
table: 'ui-widget ui-widget-content ui-corner-all',
header: 'ui-widget-header ui-corner-all ui-state-default',
icons: 'ui-icon',
sortNone: 'ui-icon-carat-2-n-s',
sortAsc: 'ui-icon-carat-1-n',
sortDesc: 'ui-icon-carat-1-s',
active: 'ui-state-active',
hover: 'ui-state-hover',
filterRow: '',
even: 'ui-widget-content',
odd: 'ui-state-default'
});
return {
testsTableId: null,
groupsTableId: null,
tpl: {
tests: createTemplate("tests-table-tpl"),
groups: createTemplate("groups-table-tpl")
},
handleHash: function (hash) {
var hashParameters = hash.split("|");
var view = hashParameters[0];
$(".tabs .tab-selected").each(function () {
$(this).removeClass("tab-selected");
});
if (view === "groups") {
$("#" + this.testsTableId).hide();
$("#" + this.groupsTableId).show();
$(".tabs .tab-groups").addClass("tab-selected");
this.handleGroupsHash(hash);
} else {
$("#" + this.groupsTableId).hide();
$("#" + this.testsTableId).show();
$(".tabs .tab-tests").addClass("tab-selected");
this.handleTestsHash(hash);
}
},
handleGroupsHash: function (hash) {
},
handleTestsHash: function (hash) {
var arguments = hash.split("|");
if (arguments.length > 1 && arguments[1] === "grouped") {
var selectedGroups = arguments[2].split(",");
if (selectedGroups.length > 0) {
$(".tests.tablesorter > tbody > tr").each(function () {
var $this = $(this);
var groupsAttr = $this.attr("data-groups");
var groups = groupsAttr.split(",");
if(haveSimilarElements(groups, selectedGroups)) {
$this.show();
} else {
$this.hide();
}
});
return;
}
}
$(".tests.tablesorter tbody tr").each(function () {
$(this).show();
});
},
renderGroupsTable: function (id, testData) {
this.groupsTableId = id;
var tests = testData.tests;
var groups = {};
for (var i = 0; i < tests.length; i++) {
var test = tests[i];
var testGroups = tests[i].groups;
if (testGroups !== null && testGroups !== undefined && Array.isArray(testGroups)) {
for (var j = 0; j < testGroups.length; j++) {
var groupName = testGroups[j];
if (groupName in groups) {
groups[groupName].tests += 1;
groups[groupName].failed += test.failed ? 1 : 0;
groups[groupName].passed += test.failed ? 0 : 1;
}
else {
groups[groupName] = {
name: groupName,
tests: 1,
failed: test.failed ? 1 : 0,
passed: test.failed ? 0 : 1
};
}
}
}
}
var groupsArray = [];
for (name in groups) {
if (groups.hasOwnProperty(name)) {
groupsArray.push(groups[name]);
}
}
setHtml(id, this.tpl.groups(groupsArray));
this.createTableSorter("#" + id + " table");
},
renderTestsTable: function (id, data) {
this.testsTableId = id;
setHtml(id, this.tpl.tests(data));
this.createTableSorter('#' + id + " table");
},
initialSorting: function () {
return [
[2, 1],
[0, 0],
[1, 0]
];
},
createTableSorter: function (selector) {
$(selector).tablesorter({
theme: 'default',
widthFixed: false,
showProcessing: false,
headerTemplate: '{content}',
onRenderTemplate: null,
onRenderHeader: function (index) {
$(this).find('div.tablesorter-header-inner').addClass('roundedCorners');
},
cancelSelection: true,
dateFormat: "mmddyyyy",
sortMultiSortKey: "shiftKey",
sortResetKey: 'ctrlKey',
usNumberFormat: true,
delayInit: false,
serverSideSorting: false,
ignoreCase: true,
sortForce: null,
sortList: this.initialSorting(),
sortAppend: null,
sortInitialOrder: "asc",
sortLocaleCompare: false,
sortReset: false,
sortRestart: false,
emptyTo: "bottom",
stringTo: "max",
textExtraction: {
0: function (node) {
return $(node).text();
},
1: function (node) {
return $(node).text();
}
},
textSorter: null,
initWidgets: true,
widgets: ['zebra', 'columns'],
widgetOptions: {
zebra: [
"ui-widget-content even",
"ui-state-default odd"],
uitheme: 'jui',
columns: [
"primary",
"secondary",
"tertiary"],
columns_tfoot: true,
columns_thead: true,
filter_childRows: false,
filter_columnFilters: true,
filter_cssFilter: "tablesorter-filter",
filter_functions: null,
filter_hideFilters: false,
filter_ignoreCase: true,
filter_reset: null,
filter_searchDelay: 300,
filter_serversideFiltering: false,
filter_startsWith: false,
filter_useParsedData: false,
resizable: true,
saveSort: true,
stickyHeaders: "tablesorter-stickyHeader"
},
initialized: function (table) {},
tableClass: 'tablesorter',
cssAsc: "tablesorter-headerSortUp",
cssDesc: "tablesorter-headerSortDown",
cssHeader: "tablesorter-header",
cssHeaderRow: "tablesorter-headerRow",
cssIcon: "tablesorter-icon",
cssChildRow: "tablesorter-childRow",
cssInfoBlock: "tablesorter-infoOnly",
cssProcessing: "tablesorter-processing",
selectorHeaders: '> thead th, > thead td',
selectorSort: "th, td",
selectorRemove: "tr.remove-me",
debug: false
});
}
};
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy