UNPKG

macedonia-protractor-reporter

Version:

an easy to use html page for looking at protractor test results with option to combine results when reruning failed tests

363 lines (317 loc) 13.9 kB
<!DOCTYPE html> <html lang="en" ng-app="jasmineResults"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.3/angular-material.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> .status { width: 85px; padding: 7px; border-radius: 3px; text-align: center; } .failed .status { background-color: rgb(255, 87, 34); } .passed .status { background-color: rgb(76, 175, 80); } .pending .status { background-color: rgb(255, 255, 0); } .failed-class { background-color: rgb(255, 87, 34); width: 85px; padding: 7px; border-radius: 3px; text-align: center; } .passed-class { background-color: rgb(76, 175, 80); width: 85px; padding: 7px; border-radius: 3px; text-align: center; } .pending2 { background-color: rgb(255, 255, 0); width: 85px; padding: 7px; border-radius: 3px; text-align: center; } /* stack traces */ pre { margin:0; } .stack.highlight { background-color: yellow; } /* console logs */ .console-logs { font-size: 12px; } .console-logs.SEVERE { color: rgb(255, 87, 34); } .modal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ z-index: 1; /* Sit on top */ padding-top: 100px; /* Location of the box */ left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */ overflow: auto; /* Enable scroll if needed */ background-color: rgb(0,0,0); /* Fallback color */ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ } /* Modal Content */ .modal-content { background-color: #fefefe; margin: auto; padding: 20px; border: 1px solid #888; width: 80%; } /* The Close Button */ .close { color: #aaaaaa; float: right; font-size: 28px; font-weight: bold; } .close:hover, .close:focus { color: #000; text-decoration: none; cursor: pointer; } </style> </head> <body ng-controller="ResultsCtrl"> <div ng-cloak layout="column"> <md-toolbar ng-class="{'md-warn': calculateStatus(results)}"> <div class="md-toolbar-tools"> <h2 flex md-truncate>Results <small ng-if="results.timer.duration"> - executed in {{ results.timer.duration / 1000 }} seconds</small></h2> <h6> <span ng-if="results.counts.passed">Passed: {{ results.counts.passed }}</span> <br ng-if="results.counts.passed"/> <span ng-if="results.counts.pending">Pending: {{ results.counts.pending }}</span> <br ng-if="results.counts.pending"/> <span ng-if="results.counts.failed">Failed: {{ results.counts.failed }}</span> <br ng-if="results.counts.failed"/> <span ng-if="results.counts.disabled">Disabled: {{ results.counts.disabled }}</span> </h6> </div> </md-toolbar> <md-content flex> <md-list> <md-list-item ng-class="result.status" ng-repeat="result in results.sequence" > <!-- Trigger/Open The Modal --> <!--<button id="{{result.id}}" onclick="displayModal(this)" >Open Modal</button>--> <div id="{{result.id}}" onclick="displayModal(this)" layout="row" flex layout-padding> <div flex="none"> <div class="status">{{ result.status }}</div> </div> <div flex="none"> <div class="">{{ result.successTimes }}/{{ result.times }}</div> </div> <div ng-if="results.options.showBrowser" flex="none"> <i ng-class="getBrowserClass(result)" class="fa"></i> </div> <div flex> <span>{{ result.prefix }}</span><strong>{{ result.description }}</strong> <div ng-if="result.pendingReason != ''"> <small>{{ result.pendingReason }}</small> </div> <!--<div ng-repeat="failure in result.failedExpectations">--> <!--<small>{{ failure.message }}</small>--> <!--</div>--> <!--<div ng-if="result.suspectLine">--> <!--<small>{{result.suspectLine}}</small>--> <!--</div>--> </div> <div flex="none" style="width: 80px; text-align:right;"> <small>{{ result.duration }}</small> </div> <!--<div flex="none" style="width: 150px">--> <!--<img width="100%" ng-if="result.screenshotPath" ng-src="{{result.screenshotPath}}"/>--> <!--</div>--> <div flex="none"> <div class="">{{ result.successTimes / result.times * 100 }} %</div> </div> </div> <!-- The Modal --> <div id="modal-{{result.id}}" class="modal"> <!-- Modal content --> <div class="modal-content"> <span id="{{result.id}}" class="close" onclick="closeModal(this)" >&times;</span> <md-list-item ng-class="result.status" ng-click="showDetail(res)" ng-repeat="res in result.allSpecs" > <div layout="row" flex layout-padding> <div flex="none"> <div ng-class="(res.status === 'passed') ? 'passed-class' : 'failed-class'" >{{ res.status }}</div> </div> <div ng-if="results.options.showBrowser" flex="none"> <i ng-class="getBrowserClass(res)" class="fa"></i> </div> <div flex> <span>{{ res.prefix }}</span><strong>{{ res.description }}</strong> <div ng-if="res.pendingReason != ''"> <small>{{ res.pendingReason }}</small> </div> <div ng-repeat="failure in res.failedExpectations"> <small>{{ failure.message }}</small> </div> <!--<div ng-if="result.suspectLine">--> <!--<small>{{result.suspectLine}}</small>--> <!--</div>--> </div> <div flex="none" style="width: 80px; text-align:right;"> <small>{{ res.duration}}</small> </div> <div flex="none" style="width: 150px"> <img width="100%" ng-if="res.screenshotPath" ng-src="{{res.screenshotPath}}"/> </div> </div> </md-list-item> </div> </div> </md-list-item> </md-list> </md-content> </div> <md-divider inset></md-divider> </md-list-item> </md-list> </md-content> </div> <!-- Dialog template --> <script type="text/ng-template" id="dialog.html"> <md-dialog aria-label="" flex="90"> <md-toolbar ng-class="getCss(activeItem)"> <div layout="row" layout-padding class="md-toolbar-tools"> <div flex="none"> <h1>Test Information:</h1> </div> <div flex> <small> <span>{{ activeItem.prefix }}</span> <strong>{{ activeItem.description }}</strong> </small> </div> </div> </md-toolbar> <md-dialog-content> <md-content> <img width="100%" ng-if="activeItem.screenshotPath" ng-src="{{activeItem.screenshotPath}}"> <!-- failed --> <md-subheader ng-if="activeItem.failedExpectations.length > 0">Stack Traces</md-subheader> <div flex layout="column" layout-padding ng-repeat="failure in activeItem.failedExpectations"> <div flex> <p>{{failure.message}}</p> <small> <pre class="stack" ng-class="{'highlight': (results.options.highlightSuspectLine && line === failure.suspectLine) }" ng-repeat="line in failure.stack.split('\n')">{{line}}</pre> </small> </div> </div> <!-- passed --> <md-subheader ng-if="activeItem.passedExpectations.length > 0">Passed Expectations</md-subheader> <div layout-padding ng-if="activeItem.passedExpectations.length > 0"> <pre ng-repeat="pass in activeItem.passedExpectations">{{ pass | json }}</pre> </div> <!-- console logs --> <md-subheader>Console Logs</md-subheader> <div class="console-logs" ng-class="log.level" flex layout="row" layout-padding ng-repeat="log in activeItem.browserLogs"> <div style="width: 75px;"> <strong>{{ log.level }}</strong> </div> <div style="width: 150px"> {{ log.timestamp | date:'yyyy-MM-dd HH:mm:ss.sss' }} </div> <div flex> {{ log.message }} </div> </div> <div layout-padding ng-if="activeItem.browserLogs.length === 0"> <em>No logs</em> </div> </md-content> </md-dialog-content> </md-dialog> </script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.3/angular-material.js"></script> <script> var RESULTS = []; </script> <script src="data/1.js"></script> <script> function displayModal(result){ // alert('a'); // alert(result.getAttribute('id')); document.getElementById('modal-'+ result.getAttribute('id')).style.display = "block"; }; function closeModal(result){ // alert('a'); // alert(result.getAttribute('id')); document.getElementById('modal-'+ result.getAttribute('id')).style.display = "none"; }; angular.module('jasmineResults', ['ngMaterial']).config(function ($mdThemingProvider) { $mdThemingProvider.theme('default').primaryPalette('green').accentPalette('yellow'); }).controller('ResultsCtrl', function ($scope, $mdDialog, RESULTS) { var classes = { 'passed': 'md-primary', 'pending': 'md-accent', 'failed': 'md-warn' }; $scope.results = RESULTS.reduce(function(combined, result) { combined.options = combined.options || result.options; combined.timer = combined.timer || result.timer; combined.sequence = combined.sequence.concat(result.sequence); // sum the counts Object.keys(result.counts).forEach(function(key) { combined.counts[key] = (combined.counts[key] || 0) + result.counts[key]; }); return combined; }, { options: null, timer: null, counts: {}, sequence: [] }); $scope.showDetail = function (item) { $scope.activeItem = item; $mdDialog.show({ controller: function () { }, scope: $scope.$new(false, $scope), templateUrl: 'dialog.html', parent: angular.element(document.body), clickOutsideToClose: true }) }; $scope.calculateStatus = function(item){ var status = 0; item.sequence.forEach(function(one) { if(one.status === "failed") status = 1; }); return status; }; $scope.getBrowserClass = function (item) { return 'fa-' + item.browserName.replace(' ', '-'); }; $scope.getCss = function (item) { return classes[item.status]; }; }).constant('RESULTS', RESULTS); </script> </body> </html>