/** * Copyright (c) 2017 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you * may not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ (function($, moment) { /** * Display the log links in a modal window. * @param linkList A list of [name, url] tuples representing log links. */ function showLinks(container, linkList) { if (!linkList || linkList.length == 0) return; var logCollection = $(''); var entries = linkList.reduce(function(acc, entry) { if (!entry || entry.length == 0) return acc; var link = ''; return acc + link; }, ''); logCollection.html(entries); if (container.find('#info-modal').length == 0) { var modal = $(''); var content = $(''); content.append('

Links

'); content.append('
'); content.appendTo(modal); var footer = $(''); footer.append('
Close'); footer.appendTo(modal); modal.appendTo(container); } var infoContainer = $('#info-modal>.modal-content>.info-container'); infoContainer.empty(); logCollection.appendTo(infoContainer); $('#info-modal').modal({dismissible: true}); $('#info-modal').modal('open'); } /** * Get the nickname for a test case result. * * Removes the result prefix and suffix, extracting only the result name. * * @param testCaseResult The string name of a VtsReportMessage.TestCaseResult. * @returns the string nickname of the result. */ function getNickname(testCaseResult) { return testCaseResult.replace('TEST_CASE_RESULT_', '') .replace('_RESULT', '') .trim() .toLowerCase(); } /** * Get the badge color from ratio value. * * @param the percentage value. * @returns the string of color for the badge. */ function getBadgeColor(ratio) { var color = "orange"; if (ratio <= 20) { color = "red"; } else if (ratio >= 70) { color = "green"; } return color; } /** * Get the rounded value. * * @param the percentage value. * @returns the rounded value from percentage value. */ function getRoundValue(ratio) { return Math.round(ratio * 1000) / 10; } /** * Display test data in the body beneath a test run's metadata. * @param container The jquery object in which to insert the test metadata. * @param data The json object containing the columns to display. * @param lineHeight The height of each list element. */ function displayTestDetails(container, data, lineHeight) { var nCol = data.length; var width = 's' + (12 / nCol); test = container; var maxLines = 0; data.forEach(function(column, index) { if (column.data == undefined || column.name == undefined) { return; } var classes = 'col test-col grey lighten-5 ' + width; if (index != nCol - 1) { classes += ' bordered'; } if (index == 0) { classes += ' left-most'; } if (index == nCol - 1) { classes += ' right-most'; } var colContainer = $('
'); var col = $('
'); colContainer.appendTo(container); var count = column.data.length; var head = $('
') .text(getNickname(column.name)) .appendTo(colContainer) .css('text-transform', 'capitalize'); $('
') .text(count) .addClass(column.name) .appendTo(head); col.appendTo(colContainer); var list = $('').appendTo(col); column.data.forEach(function(testCase) { $('
  • ') .text(testCase) .addClass('test-case') .css('font-size', lineHeight - 2) .css('line-height', lineHeight + 'px') .appendTo(list); }); if (count > maxLines) { maxLines = count; } }); var containers = container.find('.test-case-container'); containers.height(maxLines * lineHeight); } /** * Click handler for displaying test run details. * @param e The click event. */ function testRunClick(e) { var header = $(this); var icon = header.find('.material-icons.expand-arrow'); var container = header.parent().find('.test-results'); var test = header.attr('test'); var time = header.attr('time'); var url = '/api/test_run?test=' + test + '×tamp=' + time; if (header.parent().hasClass('active')) { header.parent().removeClass('active'); header.removeClass('active'); icon.removeClass('rotate'); header.siblings('.collapsible-body').stop(true, false).slideUp({ duration: 100, easing: 'easeOutQuart', queue: false, complete: function() { header.css('height', ''); } }); } else { container.empty(); header.parent().addClass('active'); header.addClass('active'); header.addClass('disabled'); icon.addClass('rotate'); $.get(url) .done(function(data) { displayTestDetails(container, data, 16); header.siblings('.collapsible-body').stop(true, false).slideDown({ duration: 100, easing: 'easeOutQuart', queue: false, complete: function() { header.css('height', ''); } }); }) .fail(function() { icon.removeClass('rotate'); }) .always(function() { header.removeClass('disabled'); }); } } /** * Append a clickable indicator link to the container. * @param container The jquery object to append the indicator to. * @param content The text to display in the indicator. * @param classes Additional space-delimited classes to add to the indicator. * @param click The click handler to assign to the indicator. * @returns The jquery object for the indicator. */ function createClickableIndicator(container, content, classes, click) { var link = $(''); link.addClass('indicator badge padded hoverable waves-effect'); link.addClass(classes); link.css('color', 'white'); link.css('margin-left', '1px'); link.append(content); link.appendTo(container); link.click(click); return link; } function displayTestMetadata(container, metadataList, showTestNames = false) { var popout = $(''); popout.attr('data-collapsible', 'expandable'); popout.addClass('collapsible popout test-runs'); popout.appendTo(container); popout.unbind(); metadataList.forEach(function(metadata) { var li = $('
  • '); li.appendTo(popout); var div = $('
    '); var test = metadata.testRun.testName; var startTime = metadata.testRun.startTimestamp; var endTime = metadata.testRun.endTimestamp; div.attr('test', test); div.attr('time', startTime); div.addClass('collapsible-header test-run'); div.appendTo(li); div.unbind().click(testRunClick); var span = $(''); span.addClass('test-run-metadata'); span.appendTo(div); span.click(function() { return false; }); if (showTestNames) { $('').text(test).appendTo(span); span.append('
    '); } if (metadata.deviceInfo) { $('').text(metadata.deviceInfo).appendTo(span); span.append('
    '); } if (metadata.abiInfo) { $('').text('ABI: ').appendTo(span) span.append(metadata.abiInfo).append('
    '); } $('').text('VTS Build: ').appendTo(span) span.append(metadata.testRun.testBuildId).append('
    '); $('').text('Host: ').appendTo(span) span.append(metadata.testRun.hostName).append('
    '); var timeString = (moment().renderTime(startTime, false) + ' - ' + moment().renderTime(endTime, true) + ' (' + moment().renderDuration(endTime - startTime) + ')'); span.append(timeString); var indicator = $(''); var color = metadata.testRun.failCount > 0 ? 'red' : 'green'; indicator.addClass('indicator badge ' + color); indicator.css('color', 'white'); indicator.append( metadata.testRun.passCount + '/' + (metadata.testRun.passCount + metadata.testRun.failCount)); indicator.appendTo(div); if (metadata.testRun.coveredLineCount != undefined && metadata.testRun.totalLineCount != undefined) { var url = ('/show_coverage?testName=' + test + '&startTime=' + startTime); var covered = metadata.testRun.coveredLineCount; var total = metadata.testRun.totalLineCount; var covPct = getRoundValue(covered / total); var color = getBadgeColor(covPct); var coverage = ('Coverage: ' + covered + '/' + total + ' (' + covPct + '%)'); createClickableIndicator(div, coverage, color, function(evt) { window.location.href = url; return false; }); } if (metadata.testRun.coveredApiCount != undefined && metadata.testRun.totalApiCount != undefined) { var covered = metadata.testRun.coveredApiCount; var total = metadata.testRun.totalApiCount; var covPct = getRoundValue(covered / total); var color = getBadgeColor(covPct); var apiCoverage = ('API Coverage: ' + covered + '/' + total + ' (' + covPct + '%)'); createClickableIndicator(div, apiCoverage, color, function(evt) { $('#apiCoverageModal') .data('urlSafeKeyList', metadata.testRun.apiCoverageKeyList); $('#apiCoverageModal').modal('open'); return false; }); } if (metadata.testRun.logLinks != undefined) { createClickableIndicator(div, 'Links', 'grey lighten-1', function() { showLinks(popout, metadata.testRun.logLinks); return false; }); } if ($('#coverageModalGraph').length) { createClickableIndicator(div, 'Graph', 'grey lighten-1', function(evt) { $('#coverageModalGraph').data('testname', test); $('#coverageModalGraph').modal('open'); $(evt.target).removeClass('grey'); $(evt.target).addClass('blue'); return false; }); } var expand = $(''); expand.addClass('material-icons expand-arrow') expand.text('expand_more'); expand.appendTo(div); var body = $('
    ') .addClass('collapsible-body test-results row') .appendTo(li); if (metadata.testDetails != undefined) { expand.addClass('rotate'); li.addClass('active'); div.addClass('active'); displayTestDetails(body, metadata.testDetails, 16); div.siblings('.collapsible-body').stop(true, false).slideDown({ duration: 0, queue: false, complete: function() { div.css('height', ''); } }); } }); } /** * Display test metadata in a vertical popout. * @param container The jquery object in which to insert the test metadata. * @param metadataList The list of metadata objects to render on the display. * @param showTestNames True to label each entry with the test module name. */ $.fn.showTests = function(metadataList, showTestNames = false) { displayTestMetadata($(this), metadataList, showTestNames); } })(jQuery, moment);