1 var util = require('util')
2 var log = require('./logger').create('reporter')
3 var MultiReporter = require('./reporters/multi')
4 var baseReporterDecoratorFactory = require('./reporters/base').decoratorFactory
5 var SourceMapConsumer = require('source-map').SourceMapConsumer
7 var createErrorFormatter = function (basePath, emitter, SourceMapConsumer) {
8 var lastServedFiles = []
10 emitter.on('file_list_modified', function (filesPromise) {
11 filesPromise.then(function (files) {
12 lastServedFiles = files.served
16 var findFile = function (path) {
17 for (var i = 0; i < lastServedFiles.length; i++) {
18 if (lastServedFiles[i].path === path) {
19 return lastServedFiles[i]
25 var URL_REGEXP = new RegExp('http:\\/\\/[^\\/]*\\/' +
26 '(base|absolute)' + // prefix
27 '((?:[A-z]\\:)?[^\\?\\s\\:]*)' + // path
29 '(\\:(\\d+))?' + // line
30 '(\\:(\\d+))?' + // column
33 return function (msg, indentation) {
34 // remove domain and timestamp from source files
35 // and resolve base path / absolute path urls into absolute path
36 msg = (msg || '').replace(URL_REGEXP, function (_, prefix, path, __, ___, line, ____, column) {
37 if (prefix === 'base') {
38 path = basePath + path
41 var file = findFile(path)
43 if (file && file.sourceMap) {
44 line = parseInt(line || '0', 10)
45 column = parseInt(column || '0', 10)
47 var smc = new SourceMapConsumer(file.sourceMap)
49 var original = smc.originalPositionFor({line: line, column: column})
51 return util.format('%s:%d:%d <- %s:%d:%d', path, line, column, original.source,
52 original.line, original.column)
54 log.warn('SourceMap position not found for trace: %s', msg)
55 // Fall back to non-source-mapped formatting.
59 return path + (line ? ':' + line : '') + (column ? ':' + column : '')
64 msg = indentation + msg.replace(/\n/g, '\n' + indentation)
71 var createReporters = function (names, config, emitter, injector) {
72 var errorFormatter = createErrorFormatter(config.basePath, emitter, SourceMapConsumer)
75 // TODO(vojta): instantiate all reporters through DI
76 names.forEach(function (name) {
77 if (['dots', 'progress'].indexOf(name) !== -1) {
78 var Cls = require('./reporters/' + name + (config.colors ? '_color' : ''))
79 return reporters.push(new Cls(errorFormatter, config.reportSlowerThan))
83 baseReporterDecorator: ['factory', baseReporterDecoratorFactory],
84 formatError: ['value', errorFormatter]
88 reporters.push(injector.createChild([locals], ['reporter:' + name]).get('reporter:' + name))
90 if (e.message.indexOf('No provider for "reporter:' + name + '"') !== -1) {
91 log.warn('Can not load "%s", it is not registered!\n ' +
92 'Perhaps you are missing some plugin?', name)
94 log.warn('Can not load "%s"!\n ' + e.stack, name)
100 reporters.forEach(function (reporter) {
101 emitter.bind(reporter)
104 return new MultiReporter(reporters)
107 createReporters.$inject = ['config.reporters', 'config', 'emitter', 'injector']
110 exports.createReporters = createReporters