UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

424 lines (349 loc) 16.3 kB
/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ Ext.define('Siesta.Project.Browser.UI.CoverageReport', { extend : 'Ext.Container', alias : 'widget.coveragereport', requires : [ 'Ext.tree.Panel', 'Siesta.Project.Browser.UI.TreeFilterField', 'Siesta.Project.Browser.UI.CoverageChart', 'Siesta.Project.Browser.Model.FilterableTreeStore', 'Siesta.Project.Browser.UI.FilterableTreeView', 'Siesta.Project.Browser.Model.CoverageUnit', 'Ext.layout.container.Border' ], cls : 'st-cov-report-panel', layout : 'border', htmlReport : null, treePanel : null, treeStore : null, chart : null, sourcePanel : null, contentContainer : null, toggleButtons : null, standalone : false, dataUrl : null, project : null, // Number of levels in the coverage class/file tree to expand by default expandLevels : 2, initComponent : function () { var me = this var standalone = this.standalone var store = this.treeStore = new Siesta.Project.Browser.Model.FilterableTreeStore({ model : 'Siesta.Project.Browser.Model.CoverageUnit', proxy : 'memory', rootVisible : true }) Ext.apply(this, { border : !this.standalone, items : [ { xtype : 'treepanel', border : false, region : 'west', enableColumnHide : false, enableColumnMove : false, enableColumnResize : false, sortableColumns : false, rowLines : false, tbar : { cls : 'siesta-toolbar', height : 45, border : false, items : [ standalone ? null : { text : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'closeText'), scale : 'medium', style : 'margin:0 10px 0 0;', handler : this.onBackToMainUI, scope : this }, { xtype : 'treefilter', cls : 'filterfield', hasAndCheck : function () { var states = Ext.pluck(me.toggleButtons, 'pressed') return !states[0] || !states[1] || !states[2] }, andChecker : this.levelFilter, andCheckerScope : this, margin : '3 0 0 0', store : store, filterField : 'text', width : 180 }, '->', { xtype : 'label', text : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'showText'), margin : '0 5 0 0' }, { text : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'highText'), level : 'high', enableToggle : true, pressed : true, scale : 'medium', cls : 'st-cov-level-high', toggleHandler : this.toggleLevels, scope : this, margin : '0 5 0 0' }, { text : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'mediumText'), level : 'med', enableToggle : true, scale : 'medium', pressed : true, cls : 'st-cov-level-medium', toggleHandler : this.toggleLevels, scope : this, margin : '0 5 0 0' }, { text : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'lowText'), level : 'low', enableToggle : true, scale : 'medium', pressed : true, cls : 'st-cov-level-low', toggleHandler : this.toggleLevels, scope : this, style : 'margin:0 5px 0 0' } ] }, viewType : 'filterabletreeview', viewConfig : { store : store.nodeStore, trackOver : false, rootVisible : true }, cls : 'st-cov-report-tree-panel', flex : 1, split : true, rootVisible : true, columns : [ { xtype : 'treecolumn', dataIndex : 'text', menuDisabled : true, flex : 3 }, { text : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'statementsText'), flex : 1, menuDisabled : true, tdCls : 'cov-result-cell', renderer : this.getMetricsRenderer('statements') }, { text : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'branchesText'), flex : 1, menuDisabled : true, tdCls : 'cov-result-cell', renderer : this.getMetricsRenderer('branches') }, { text : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'functionsText'), flex : 1, menuDisabled : true, tdCls : 'cov-result-cell', renderer : this.getMetricsRenderer('functions') }, { text : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'linesText'), flex : 1, menuDisabled : true, tdCls : 'cov-result-cell', renderer : this.getMetricsRenderer('lines') } ], store : store, listeners : { selectionchange : this.onClassSelected, scope : this } }, { xtype : 'container', cls : 'coveragechart-container', slot : 'contentContainer', region : 'center', layout : { type : 'card', deferredRendering : true }, items : [ { xtype : 'coveragechart' }, { xtype : 'panel', slot : 'sourcePanel', flex : 1, autoScroll : true, bodyPadding : '4 0 4 10', border : false, cls : 'st-cov-report-source-panel' } ] } ] }) this.callParent() this.contentContainer = this.down('[slot=contentContainer]') this.chart = this.down('chart') this.sourcePanel = this.down('[slot=sourcePanel]') this.toggleButtons = this.query('button[level]') this.treePanel = this.down('treepanel') if (standalone) { // `loadingMask.show()` throws exception when called with non-rendered target this.on('afterrender', function () { var loadingMask = new Ext.LoadMask({ target : this, msg : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'loadingText') }); loadingMask.show() // use this code for testing // setTimeout(function () { // loadingMask.hide() // // me.loadHtmlReport(me.htmlReport) // }, 2000) Ext.Ajax.request({ url : this.dataUrl, success : function (response) { loadingMask.hide() me.loadHtmlReport(Ext.JSON.decode(response.responseText)) }, failure : function () { loadingMask.hide() Ext.Msg.show({ title : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'loadingErrorText'), msg : Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'loadingErrorMessageText') + me.dataUrl, buttons : Ext.MessageBox.OK, icon : Ext.MessageBox.ERROR }) } }) }, this, { single : true }) } else if (this.htmlReport) { this.loadHtmlReport(this.htmlReport); } // Refresh data is user reruns a test with coverage panel open if (this.project) { this.project.on('testsuiteend', this.onTestSuiteEnd, this) } }, onTestSuiteEnd : function (descriptors) { if (this.project && this.isVisible()) { // Load new data into coverage report this.loadHtmlReport(this.project.generateCoverageHtmlReport(false)); } }, loadHtmlReport : function (report) { this.htmlReport = report var treeStore = this.treeStore var isFile = report.coverageUnit == 'file' var treeFilter = this.down('treefilter') var selModel = this.treePanel.getSelectionModel(); var selected = selModel.getSelected(); var oldSelectedId = selected.length > 0 ? selected.first().getId() : null; treeStore.setRootNode(this.generateFilesTree(report.htmlReport.root)) if (oldSelectedId && treeStore.getNodeById(oldSelectedId)){ selModel.select(treeStore.getNodeById(oldSelectedId)); } this.down('treecolumn').setText(isFile ? 'File name' : 'Class name') treeFilter.emptyText = isFile ? 'Filter files' : 'Filter classes' treeFilter.applyEmptyText(); this.loadChartData(treeStore.getRootNode()); }, levelFilter : function (node) { var coverage = node.getStatementCoverage(); if (coverage === undefined) return false; return this.toggleButtons[coverage >= 80 ? 0 : coverage >= 50 ? 1 : 2].pressed }, toggleLevels : function () { this.down('treefilter').refreshFilter() }, getCoverageLevelClass : function (coveragePct) { if (typeof coveragePct == 'number') return 'st-cov-level-' + (coveragePct >= 80 ? 'high' : coveragePct >= 50 ? 'medium' : 'low'); else return '' }, getMetricsRenderer : function (property) { var me = this return function (value, metaData, preloadFile) { var reportNode = preloadFile.get('reportNode') if (!reportNode) return '' var metrics = reportNode.metrics[property] metaData.tdCls = me.getCoverageLevelClass(metrics.pct) return '<span class="st-cov-stat-pct-' + property + '">' + Math.round(metrics.pct) + '%</span> ' + '<span class="st-cov-stat-abs-' + property + '">(' + metrics.covered + '/' + metrics.total + ')</span>' } }, generateFilesTree : function (node, depth) { var me = this depth = depth || 0; // in this method "node" should be treated as a raw JSON object and not an instance of Node from Istanbul // (even that in UI usage scenario it will be a Node) // since for the standalone report we load a JSON blob with the tree report // so we should not call any methods on "node" if (node.kind === 'dir') { var text = node.relativeName || node.fullName return { id : node.fullName, url : node.fullName, leaf : false, expanded : depth < this.expandLevels, text : text == '/' && this.htmlReport.coverageUnit == 'extjs_class' ? Siesta.Resource('Siesta.Project.Browser.UI.CoverageReport', 'globalNamespaceText') : text, reportNode : node, children : Ext.Array.map(node.children, function (childNode) { return me.generateFilesTree(childNode, depth + 1) }).sort(this.treeSorterFn) } } else { return { id : node.fullName, url : node.fullName, leaf : true, text : node.relativeName, reportNode : node } } }, treeSorterFn : function (node1, node2) { if (!node1.leaf && node2.leaf) return -1; if (node1.leaf && !node2.leaf) return 1; if (node1.leaf === node2.leaf) return node1.text < node2.text ? -1 : 1; }, onClassSelected : function (view, records) { var record = records[0]; if (!record) return; if (record.isLeaf() && !this.htmlReport.coverageNoSource) { this.sourcePanel.update(record.get('reportNode').html) prettyPrint() this.contentContainer.getLayout().setActiveItem(1) } else { this.loadChartData(record) this.contentContainer.getLayout().setActiveItem(0) } }, onBackToMainUI : function () { this.fireEvent('backtomainui', this) }, loadChartData : function (node) { this.chart.store.loadData([ { name : 'Statements', value : Math.round(node.getStatementCoverage()) }, { name : 'Branches', value : Math.round(node.getBranchCoverage()) }, { name : 'Functions', value : Math.round(node.getFunctionCoverage()) }, { name : 'Lines', value : Math.round(node.getLineCoverage()) } ]) } });