UNPKG

testem

Version:

Test'em 'scripts! Javascript Unit testing made easy.

281 lines (263 loc) 8.07 kB
'use strict'; var View = require('./view'); var ScrollableTextPanel = require('./scrollable_text_panel'); var tabs = require('./constants'); var styledString = require('styled_string'); var Chars = require('../../utils/chars'); var indent = require('../../utils/strutils').indent; var Screen = require('./screen'); function failureDisplay(item) { var extra = []; var stacktrace = item.stack; if (stacktrace) { var stacklines = stacktrace.split('\n'); if (stacklines[0] === item.message) { stacktrace = stacklines.slice(1).map(function(line) { return line.trim(); }).join('\n'); } extra.push(stacktrace); } else { if (item.file) { extra.push(item.file); } if (item.line) { extra.push(' ' + item.line); } } if (item.expected) { extra.push(' expected ' + (item.negative ? 'NOT ' : '') + item.expected); } if (item.actual) { extra.push(' actual ' + item.actual); } if (item.at) { extra.push(' at ' + item.at); } return Chars.cross + ' ' + (item.message || 'failed') + (extra ? '\n' + indent(extra.join('\n')) : ''); } function failedTestDisplay(test) { var failedItems = (test.get('items') || []).filter(function(item) { return !item.passed; }); return test.get('name') + '\n' + indent(failedItems.map(failureDisplay).join('\n')); } module.exports = View.extend({ defaults: { visible: false, focus: 'top' }, initialize: function() { if (!this.get('screen')) { this.set('screen', new Screen()); } var runner = this.get('runner'); var results = runner.get('results'); var messages = runner.get('messages'); var appview = this.get('appview'); var visible = this.get('visible'); var self = this; var screen = this.get('screen'); var topPanel = this.topPanel = new ScrollableTextPanel({ line: tabs.TabStartLine + tabs.TabHeight - 1, col: 0, visible: visible, screen: screen }); var bottomPanel = this.bottomPanel = new ScrollableTextPanel({ col: 0, visible: visible, screen: screen }); this.observe(appview, 'change:cols change:lines', function() { self.syncDimensions(); self.render(); }); if (results) { this.observe(results, 'change', function() { self.syncDimensions(); self.syncResultsDisplay(); }); } this.observe(messages, 'reset add remove', function() { self.syncDimensions(); self.syncMessages(); }); this.observe(this, 'change:visible', function() { var visible = self.get('visible'); topPanel.set('visible', visible, {silent: true}); bottomPanel.set('visible', visible, {silent: true}); self.syncDimensions({silent: true}); self.render(); }); this.syncDimensions({silent: true}); this.syncResultsDisplay({silent: true}); this.syncMessages({silent: true}); this.render(); }, toggleFocus: function() { var focus = this.get('focus'); this.set('focus', focus === 'top' ? 'bottom' : 'top'); }, resetScrollPositions: function() { this.topPanel.set('scrollOffset', 0); this.bottomPanel.set('scrollOffset', 0); }, targetPanel: function() { var runner = this.get('runner'); var bottomPanel = this.bottomPanel; var topPanel = this.topPanel; if (runner.hasMessages() && runner.hasResults()) { return (this.get('focus') === 'top') ? topPanel : bottomPanel; } else if (runner.hasMessages()) { return bottomPanel; } else if (runner.hasResults()) { return topPanel; } else { return topPanel; } }, scrollUp: function() { this.targetPanel().scrollUp(); }, scrollDown: function() { this.targetPanel().scrollDown(); }, pageUp: function() { this.targetPanel().pageUp(); }, pageDown: function() { this.targetPanel().pageDown(); }, halfPageUp: function() { this.targetPanel().halfPageUp(); }, halfPageDown: function() { this.targetPanel().halfPageDown(); }, syncMessages: function(options) { this.bottomPanel.set('text', this.getMessagesText(), options); }, syncResultsDisplay: function(options) { this.topPanel.set('text', this.getResultsDisplayText(), options); }, syncDimensions: function(options) { var appview = this.get('appview'); var termCols = appview.get('cols'); var termLines = appview.get('lines'); var runner = this.get('runner'); if (runner.hasMessages() && runner.hasResults()) { var midLine = Math.floor((termLines - tabs.LogPanelUnusedLines) / 2); this.topPanel.set({ height: midLine, width: termCols }, options); var line = midLine + tabs.TabStartLine + tabs.TabHeight - 1; var bottomPanelAttrs = { line: line, height: termLines - line - 1, width: termCols }; this.bottomPanel.set(bottomPanelAttrs, options); } else if (runner.hasMessages()) { // only has messages this.topPanel.set({ height: 0, width: termCols }, options); var height = termLines - tabs.LogPanelUnusedLines; this.bottomPanel.set({ line: tabs.TabStartLine + tabs.TabHeight - 1, height: height, width: termCols }, options); } else { // only has results // Hide the bottom panel if there are no messages // to be displayed var topPanelHeight = termLines - tabs.LogPanelUnusedLines; this.topPanel.set({ height: topPanelHeight, width: termCols }, options); this.bottomPanel.set({ line: tabs.TabStartLine + tabs.TabHeight + topPanelHeight, height: 0, width: termCols }, options); } }, render: function() { this.topPanel.render(); this.bottomPanel.render(); }, getResultsDisplayText: function() { var runner = this.get('runner'); var results = runner.get('results'); var topLevelError = results ? results.get('topLevelError') : null; var tests = null; var out = ''; var pendingOut = ''; if (topLevelError) { out += 'Top Level:\n' + indent(topLevelError) + '\n\n'; } if (results && (tests = results.get('tests'))) { var total = results.get('total'); var pending = results.get('pending'); var allDone = results.get('all'); if (!total) { out = allDone ? 'No tests were run :(' : 'Please be patient :)'; } else { var failedTests = tests.filter(function(test) { return test.get('failed') > 0; }); if (failedTests.length > 0) { out += failedTests.map(failedTestDisplay).join('\n'); } else { // All passed if (allDone) { var pendingTests = tests.filter(function(test) { return test.get('pending') > 0; }); out += Chars.success + ' ' + total + ' tests complete'; if (pending > 0) { out += ' (' + pending + ' pending)'; } out += '.'; if (pending) { pendingOut += '\n\n'; pendingOut += pendingTests.map(function(test) { return '[PENDING] ' + test.get('name'); }).join('\n'); } } else { out += 'Looking good...'; } } } } return styledString(out, {foreground: 'cyan'}) .append(styledString(pendingOut, {foreground: 'yellow'})); }, getMessagesText: function() { var messages = this.get('runner').get('messages'); var retval = styledString(''); messages.forEach(function(message) { var type = message.get('type'); var text = message.get('text'); var color = 'yellow'; switch (type) { case 'warn': color = 'cyan'; break; case 'info': color = 'green'; break; case 'error': color = 'red'; break; } retval = retval.concat(styledString(text, {foreground: color})); }); return retval; } });