<commit_before>/*
 * Copyright (c) 2012 <NAME>
 * Copyright (c) 2012 "Cowboy" <NAME>
 * Licensed under the MIT license.
 * http://benalman.com/about/license/
 */

/*jshint node:true, curly:false*/
"use strict";

var fs = require('fs'),
    path = require('path'),
    connect = require('connect'),
    URL = require('url'),
    open = require('open');

var grunt, phantomjs;

var baseDir = '.';
var tmpRunner = '_SpecRunner.html';

var options, defaultOptions = {
  timeout : 10000,
  specs   : [],
  src     : [],
  helpers : [],
  phantomjs : {}
};


module.exports = function(g){
  grunt = g;
  grunt.util = grunt.utils;

  phantomjs = require('./lib/phantomjs').init(grunt);

  grunt.registerTask('jasmine', 'Run jasmine specs headlessly through PhantomJS.', function() {
    options = grunt.config('jasmine');

    var done = this.async();

    grunt.helper('jasmine-phantom-runner', options, function(err,status) {
      if (status && status.failed > 0) {
        grunt.log.error(grunt.util._("%s of %s total specs failed").sprintf(status.failed, status.total));
      }
      if (err) grunt.log.error(err);
      done(!err && status.failed === 0);
    });

  });

  // Convenience/test task. Never finishes and needs to be closes with ^C
  // Used to troubleshoot jasmine tasks outside of phantomjs
  grunt.registerTask('jasmine-server', 'Run jasmine specs headlessly through PhantomJS.', function() {
    var done   = this.async();
    grunt.helper('jasmine-interactive-runner', grunt.config('jasmine'));
  });

  grunt.registerHelper('jasmine-phantom-runner',function(options,cb){
    options = grunt.util._.extend({},defaultOptions,options);

    var phantomReporters = [
        grunt.task.getFile('jasmine/reporters/ConsoleReporter.js'),
        grunt.task.getFile('jasmine/reporters/JUnitReporter.js')
      ],
      port = (options.server && options.server.port) || 8888;

    var url = URL.format({
      protocol : 'http',
      hostname : '127.0.0.1',
      port : port + '',
      pathname : path.join(baseDir,tmpRunner)
    });

    grunt.verbose.subhead('Testing jasmine specs via phantom').or.writeln('Testing jasmine specs via phantom');
    grunt.helper('jasmine-build-specrunner', baseDir, options, phantomReporters);
    var server = grunt.helper('static-server', baseDir, port);

    runPhantom(url,options,phantomReporters.length,function(err,status){
      server.close();
      if (typeof cb === 'function') cb(err,status)
    });
  });

  grunt.registerHelper('jasmine-interactive-runner',function(options,cb){
    options = grunt.util._.extend({},defaultOptions,options);

    var port = (options.server && options.server.port) || 8888;

    var url = URL.format({
      protocol : 'http',
      hostname : '127.0.0.1',
      port : port + '',
      pathname : path.join(baseDir,tmpRunner)
    });

    grunt.helper('jasmine-build-specrunner', baseDir, options, []);
    grunt.helper('static-server', baseDir, port);
    open(url)
    if (typeof cb === 'function') cb();
  });

  grunt.registerHelper('jasmine-build-specrunner', function(dir, options, reporters){
    var jasmineCss = [
      __dirname + '/../jasmine/lib/jasmine-core/jasmine.css'
    ];

    var jasmineCore = [
      __dirname + '/../jasmine/lib/jasmine-core/jasmine.js',
      __dirname + '/../jasmine/lib/jasmine-core/jasmine-html.js'
    ];

    var phantomHelper = __dirname + '/jasmine/phantom-helper.js';
    var jasmineHelper = __dirname + '/jasmine/jasmine-helper.js';

    var styles = getRelativeFileList(jasmineCss);
    var scripts = getRelativeFileList(jasmineCore, options.src, options.helpers, options.specs, phantomHelper, reporters, jasmineHelper);

    var specRunnerTemplate = __dirname + '/../jasmine/SpecRunner.tmpl';

    var source;
    grunt.file.copy(specRunnerTemplate, path.join(dir,tmpRunner), {
      process : function(src) {
        source = grunt.util._.template(src, {
          scripts : scripts,
          css : styles
        });
        return source
      }
    });
    return source;
  });

  // stolen from grunt/task/server. Might be misunderstanding grunt tasks, but it didn't seem very reusable
  grunt.registerHelper('static-server',function(base, port) {
    base = path.resolve(base);

    var server = connect();

    if (grunt.option('debug')) {
      connect.logger.format('grunt', ('[D] local server :method :url :status ' + ':res[content-length] - :response-time ms').magenta);
      server.use(connect.logger('grunt'));
    }

    server.use(connect.static(base));
    server.use(connect.directory(base));

    grunt.verbose.writeln('Starting static web server on port ' + port);
    return server.listen(port);
  });

  phantomjs.on('fail.timeout',function(){
    grunt.log.writeln();
    grunt.warn('PhantomJS timed out, possibly due to an unfinished async spec.', 90);
  });

  phantomjs.on('console',console.log.bind(console));
  phantomjs.on('verbose',grunt.verbose.writeln.bind(grunt.verbose));
  phantomjs.on('debug', grunt.log.debug.bind(grunt.log, 'phantomjs'));
  phantomjs.on('write', grunt.log.write.bind(grunt.log));
  phantomjs.on('writeln', grunt.log.writeln.bind(grunt.log));
  phantomjs.on('onError',function(string, trace){
    if (trace) {
      console.log(trace.stack.red);
    } else {
      console.log(string.red);
    }
  });

  phantomjs.on('jasmine.*', function() {
    //var args = [this.event].concat(grunt.util.toArray(arguments));
    // grunt 0.4.0
    // grunt.event.emit.apply(grunt.event, args);
  });

};


function runPhantom(url,options,numReporters, cb) {
  var status;
  setupTestListeners(options,numReporters,function(testStatus){
    status = testStatus;
  });
  phantomjs.spawn(url, {
    failCode : 90,
    options  : options,
    done     : function(err){<commit_msg>Adding check for trace.stack on error.<commit_after>/*
 * Copyright (c) 2012 <NAME>
 * Copyright (c) 2012 "Cowboy" <NAME>
 * Licensed under the MIT license.
 * http://benalman.com/about/license/
 */

/*jshint node:true, curly:false*/
"use strict";

var fs = require('fs'),
    path = require('path'),
    connect = require('connect'),
    URL = require('url'),
    open = require('open');

var grunt, phantomjs;

var baseDir = '.';
var tmpRunner = '_SpecRunner.html';

var options, defaultOptions = {
  timeout : 10000,
  specs   : [],
  src     : [],
  helpers : [],
  phantomjs : {}
};


module.exports = function(g){
  grunt = g;
  grunt.util = grunt.utils;

  phantomjs = require('./lib/phantomjs').init(grunt);

  grunt.registerTask('jasmine', 'Run jasmine specs headlessly through PhantomJS.', function() {
    options = grunt.config('jasmine');

    var done = this.async();

    grunt.helper('jasmine-phantom-runner', options, function(err,status) {
      if (status && status.failed > 0) {
        grunt.log.error(grunt.util._("%s of %s total specs failed").sprintf(status.failed, status.total));
      }
      if (err) grunt.log.error(err);
      done(!err && status.failed === 0);
    });

  });

  // Convenience/test task. Never finishes and needs to be closes with ^C
  // Used to troubleshoot jasmine tasks outside of phantomjs
  grunt.registerTask('jasmine-server', 'Run jasmine specs headlessly through PhantomJS.', function() {
    var done   = this.async();
    grunt.helper('jasmine-interactive-runner', grunt.config('jasmine'));
  });

  grunt.registerHelper('jasmine-phantom-runner',function(options,cb){
    options = grunt.util._.extend({},defaultOptions,options);

    var phantomReporters = [
        grunt.task.getFile('jasmine/reporters/ConsoleReporter.js'),
        grunt.task.getFile('jasmine/reporters/JUnitReporter.js')
      ],
      port = (options.server && options.server.port) || 8888;

    var url = URL.format({
      protocol : 'http',
      hostname : '127.0.0.1',
      port : port + '',
      pathname : path.join(baseDir,tmpRunner)
    });

    grunt.verbose.subhead('Testing jasmine specs via phantom').or.writeln('Testing jasmine specs via phantom');
    grunt.helper('jasmine-build-specrunner', baseDir, options, phantomReporters);
    var server = grunt.helper('static-server', baseDir, port);

    runPhantom(url,options,phantomReporters.length,function(err,status){
      server.close();
      if (typeof cb === 'function') cb(err,status)
    });
  });

  grunt.registerHelper('jasmine-interactive-runner',function(options,cb){
    options = grunt.util._.extend({},defaultOptions,options);

    var port = (options.server && options.server.port) || 8888;

    var url = URL.format({
      protocol : 'http',
      hostname : '127.0.0.1',
      port : port + '',
      pathname : path.join(baseDir,tmpRunner)
    });

    grunt.helper('jasmine-build-specrunner', baseDir, options, []);
    grunt.helper('static-server', baseDir, port);
    open(url)
    if (typeof cb === 'function') cb();
  });

  grunt.registerHelper('jasmine-build-specrunner', function(dir, options, reporters){
    var jasmineCss = [
      __dirname + '/../jasmine/lib/jasmine-core/jasmine.css'
    ];

    var jasmineCore = [
      __dirname + '/../jasmine/lib/jasmine-core/jasmine.js',
      __dirname + '/../jasmine/lib/jasmine-core/jasmine-html.js'
    ];

    var phantomHelper = __dirname + '/jasmine/phantom-helper.js';
    var jasmineHelper = __dirname + '/jasmine/jasmine-helper.js';

    var styles = getRelativeFileList(jasmineCss);
    var scripts = getRelativeFileList(jasmineCore, options.src, options.helpers, options.specs, phantomHelper, reporters, jasmineHelper);

    var specRunnerTemplate = __dirname + '/../jasmine/SpecRunner.tmpl';

    var source;
    grunt.file.copy(specRunnerTemplate, path.join(dir,tmpRunner), {
      process : function(src) {
        source = grunt.util._.template(src, {
          scripts : scripts,
          css : styles
        });
        return source
      }
    });
    return source;
  });

  // stolen from grunt/task/server. Might be misunderstanding grunt tasks, but it didn't seem very reusable
  grunt.registerHelper('static-server',function(base, port) {
    base = path.resolve(base);

    var server = connect();

    if (grunt.option('debug')) {
      connect.logger.format('grunt', ('[D] local server :method :url :status ' + ':res[content-length] - :response-time ms').magenta);
      server.use(connect.logger('grunt'));
    }

    server.use(connect.static(base));
    server.use(connect.directory(base));

    grunt.verbose.writeln('Starting static web server on port ' + port);
    return server.listen(port);
  });

  phantomjs.on('fail.timeout',function(){
    grunt.log.writeln();
    grunt.warn('PhantomJS timed out, possibly due to an unfinished async spec.', 90);
  });

  phantomjs.on('console',console.log.bind(console));
  phantomjs.on('verbose',grunt.verbose.writeln.bind(grunt.verbose));
  phantomjs.on('debug', grunt.log.debug.bind(grunt.log, 'phantomjs'));
  phantomjs.on('write', grunt.log.write.bind(grunt.log));
  phantomjs.on('writeln', grunt.log.writeln.bind(grunt.log));
  phantomjs.on('onError',function(string, trace){
    if (trace && trace.stack) {
      console.log(trace.stack.red);
    } else {
      console.log(string.red);
    }
  });

  phantomjs.on('jasmine.*', function() {
    //var args = [this.event].concat(grunt.util.toArray(arguments));
    // grunt 0.4.0
    // grunt.event.emit.apply(grunt.event, args);
  });

};


function runPhantom(url,options,numReporters, cb) {
  var status;
  setupTestListeners(options,numReporters,function(testStatus){
    status = testStatus;
  });
  phantomjs.spawn(url, {
    failCode : 90,
    options  : options,
    done     : function(err){
{'fraction_non_alphanumeric': 0.16188418323249784, 'fraction_numerical': 0.007260155574762317, 'mean_word_length': 3.3680634201585504, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '301423', 'n_tokens_mistral': 3997, 'n_tokens_neox': 3675, 'n_words': 709}