<commit_before>var tilelive = require('tilelive');
var TileJSON = require('tilejson');
var url = require('url');
var assert = require('assert');
var path = require('path');
var fs = require('fs');
var crypto = require('crypto');
var Vector = require('..');

function md5(str) {
    return crypto.createHash('md5').update(str).digest('hex');
}

// Load fixture data.
var fixtureDir = path.resolve(__dirname, 'fixtures', 'tm2z'),
    remotePath = 'http://mapbox.s3.amazonaws.com/tilelive-vector/test-tm2z.tm2z',
    xml = fs.readFileSync(path.join(fixtureDir, 'project', 'project.xml'));

// Register vector:, tm2z:, tm2z+http: and mapbox: tilelive protocols
Vector.registerProtocols(tilelive);
tilelive.protocols['mapbox:'] = function Source(uri, callback) {
    return new TileJSON('http://a.tiles.mapbox.com/v3' + uri.pathname + '.json', callback);
};

// Register font
Vector.mapnik.register_fonts(path.join(__dirname, 'fonts', 'source-sans-pro'));

describe('tm2z', function() {
    it('exposes the mapnik binding', function() {
        assert.ok(Vector.mapnik);
    });
    it('loads a tm2z url', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
            assert.ifError(err);
            done();
        });
    });
    it('matches expected xml', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
            assert.ifError(err);
            assert.equal(source._xml, xml);
            done();
        });
    });
    it('gunzips then untars', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tar.gz'), function(err, source) {
            assert.ifError(err);
            done();
        });
    });
    it('errors out if not gzipped', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tar'), function(err, source) {
            assert.equal(err.code, 'Z_DATA_ERROR');
            assert.equal(err.message, 'incorrect header check');
            done();
        });
    });
    it('errors out on bad gunzip', function(done) {
       tilelive.load('tm2z://' + path.join(fixtureDir, 'doublezip.tm2z'), function(err, source) {
            assert.equal(err.message, 'invalid tar file');
            done();
        });
    });
    it('errors out if file size exceeds max size', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'filesize.tm2z'), function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Upload size should not exceed 750KB.');
            done();
        });
    });
    it('errors out if file size exceeds custom max size', function(done) {
        tilelive.load({
            protocol: 'tm2z:',
            pathname: fixtureDir + '/filesize.tm2z',
            filesize: 500 * 1024
        }, function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Upload size should not exceed 500KB.');
            done();
        });
    });
    it('errors out if unzipped size exceeds max size', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'gunzipsize.tm2z'), function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Unzipped size should not exceed 5MB.');
            done();
        });
    });
    it('errors out if unzipped size exceeds custom max size', function(done) {
        tilelive.load({
            protocol: 'tm2z:',
            pathname: fixtureDir + '/gunzipsize.tm2z',
            gunzipsize: 1024 * 1024
        }, function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Unzipped size should not exceed 1MB.');
            done();
        });
    });
    it('errors out if unzipped project.xml size exceeds max size', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'xmlsize.tm2z'), function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Unzipped project.xml size should not exceed 750KB.');
            done();
        });
    });
    it('errors out if unzipped project.xml size exceeds custom max size', function(done) {
        tilelive.load({
            protocol: 'tm2z:',
            pathname: fixtureDir + '/xmlsize.tm2z',
            xmlsize: 300 * 1024
        }, function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Unzipped project.xml size should not exceed 300KB.');
            done();
        });
    });
    it('errors out if not a directory', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'nodirectory.tm2z'), function(err, source) {
            assert.equal(err.message.split(',')[0], 'EISDIR');
            done();
        });
    });
    it('errors out if missing project.xml', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'empty.tm2z'), function(err, source) {
            assert.equal(err.message, 'project.xml not found in package');
            done();
        });
    });
    it('errors out on invalid project.xml', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'malformed.tm2z'), function(err, source) {
            assert.equal(err.message.split(':')[0], 'expected < at line 1');
            done();
        });
    });
    it('errors out if style references a missing font', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'missing_font.tm2z'), function(err, source) {
            assert.equal('EMAPNIK', err.code);
            assert.equal(err.message.split("'")[0], 'Failed to find font face ');
            done();
        });
    });
    it('does not error out if style references a registered font', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
            assert.ifError(err);
            done();
        });
    });
    it('errors out if style references a missing image', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'missing_image.tm2z'), function(err, source) {
            assert.equal('EMAPNIK', err.code);
            assert.equal(err.message.split(':')[0], 'file could not be found');
            done();
        });
    });
    it('profiles a tm2z file', function(done) {
        this.timeout(0);
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
            assert.ifError(err);
            source.profile(function(err, profile) {
                assert.ifError(err);
                assert.deepEqual([
                    'tiles',
                    'xmltime',
                    'drawtime',
                    'loadtime',
                    'srcbytes',
                    'imgbytes'
                ], Object.keys(profile));
                assert.equal('number', typeof profile.xmltime);
                assert.deepEqual(['avg','min','max'], Object.keys(profile.drawtime));
                assert.deepEqual(['avg','min','max'], Object.keys(profile.loadtime));
                assert.deepEqual(['avg','min','max'], Object.keys(profile.srcbytes));
                assert.deepEqual(['avg','min','max'], Object.keys(profile.imgbytes));
                assert.deepEqual([
                    '0/0/0',
                    '1/1/0',
                    '2/2/1',
                    '3/4/3',
                    '4/9/7',
                    '5/19/14',
                    '6/39/29',
                    '7/79/58',
                    '8/159/117',
                    '9/319/235',
                    '10/638/470',
                    '11/1276/940',
                    '12/2553/1880',
                    '13/5106/3761',
                    '14/10212/7522',
                    '15/20424/15045',
                    '16/40849/30091',
                    '17/81699/60182',
                    '18/163398/120364',
                    '19/326797/240728',
                    '20/653594/481456',
                    '21/1307188/962913',
                    '22/2614376/1925826'
                ], profile.tiles.map(function(t) { return t.z + '/' + t.x + '/' + t.y }));
                done();
            });
        });
    });
});

describe('tm2z+http', function() {
    it('loads a tm2z+http url', function(done) {
        this.timeout(5000);
        tilelive.load('tm2z+' + remotePath, function(err, source) {
            assert.ifError(err);
            done();
        });
    });
    it('matches expected xml', function(done) {
        this.timeout(5000);
        tilelive.load('tm2z+' + remotePath, function(err, source) {
            assert.ifError(err);
            assert.equal(xml, source._xml);
            done();
        });
    });
    it('errors out on an invalid S3 url', function(done) {
        tilelive.load('tm2z+http://mapbox.s3.amazonaws.com/tilelive-vector/invalid.tm2z', function(err, source) {
            assert.equal('Z_DATA_ERROR', err.code);
            done();
        });
    });
});
<commit_msg>more path.joining<commit_after>var tilelive = require('tilelive');
var TileJSON = require('tilejson');
var url = require('url');
var assert = require('assert');
var path = require('path');
var fs = require('fs');
var crypto = require('crypto');
var Vector = require('..');

function md5(str) {
    return crypto.createHash('md5').update(str).digest('hex');
}

// Load fixture data.
var fixtureDir = path.resolve(__dirname, 'fixtures', 'tm2z'),
    remotePath = 'http://mapbox.s3.amazonaws.com/tilelive-vector/test-tm2z.tm2z',
    xml = fs.readFileSync(path.join(fixtureDir, 'project', 'project.xml'));

console.log(fixtureDir);

// Register vector:, tm2z:, tm2z+http: and mapbox: tilelive protocols
Vector.registerProtocols(tilelive);
tilelive.protocols['mapbox:'] = function Source(uri, callback) {
    return new TileJSON('http://a.tiles.mapbox.com/v3' + uri.pathname + '.json', callback);
};

// Register font
Vector.mapnik.register_fonts(path.join(__dirname, 'fonts', 'source-sans-pro'));

describe('tm2z', function() {
    it('exposes the mapnik binding', function() {
        assert.ok(Vector.mapnik);
    });
    it('loads a tm2z url', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
            assert.ifError(err);
            done();
        });
    });
    it('matches expected xml', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
            assert.ifError(err);
            assert.equal(source._xml, xml);
            done();
        });
    });
    it('gunzips then untars', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tar.gz'), function(err, source) {
            assert.ifError(err);
            done();
        });
    });
    it('errors out if not gzipped', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tar'), function(err, source) {
            assert.equal(err.code, 'Z_DATA_ERROR');
            assert.equal(err.message, 'incorrect header check');
            done();
        });
    });
    it('errors out on bad gunzip', function(done) {
       tilelive.load('tm2z://' + path.join(fixtureDir, 'doublezip.tm2z'), function(err, source) {
            assert.equal(err.message, 'invalid tar file');
            done();
        });
    });
    it('errors out if file size exceeds max size', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'filesize.tm2z'), function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Upload size should not exceed 750KB.');
            done();
        });
    });
    it('errors out if file size exceeds custom max size', function(done) {
        tilelive.load({
            protocol: 'tm2z:',
            pathname: path.join(fixtureDir, 'filesize.tm2z'),
            filesize: 500 * 1024
        }, function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Upload size should not exceed 500KB.');
            done();
        });
    });
    it('errors out if unzipped size exceeds max size', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'gunzipsize.tm2z'), function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Unzipped size should not exceed 5MB.');
            done();
        });
    });
    it('errors out if unzipped size exceeds custom max size', function(done) {
        tilelive.load({
            protocol: 'tm2z:',
            pathname: path.join(fixtureDir, 'gunzipsize.tm2z'),
            gunzipsize: 1024 * 1024
        }, function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Unzipped size should not exceed 1MB.');
            done();
        });
    });
    it('errors out if unzipped project.xml size exceeds max size', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'xmlsize.tm2z'), function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Unzipped project.xml size should not exceed 750KB.');
            done();
        });
    });
    it('errors out if unzipped project.xml size exceeds custom max size', function(done) {
        tilelive.load({
            protocol: 'tm2z:',
            pathname: path.join(fixtureDir, 'xmlsize.tm2z'),
            xmlsize: 300 * 1024
        }, function(err, source) {
            assert.equal(err instanceof RangeError, true);
            assert.equal(err.message, 'Unzipped project.xml size should not exceed 300KB.');
            done();
        });
    });
    it('errors out if not a directory', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'nodirectory.tm2z'), function(err, source) {
            assert.equal(err.message.split(',')[0], 'EISDIR');
            done();
        });
    });
    it('errors out if missing project.xml', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'empty.tm2z'), function(err, source) {
            assert.equal(err.message, 'project.xml not found in package');
            done();
        });
    });
    it('errors out on invalid project.xml', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'malformed.tm2z'), function(err, source) {
            assert.equal(err.message.split(':')[0], 'expected < at line 1');
            done();
        });
    });
    it('errors out if style references a missing font', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'missing_font.tm2z'), function(err, source) {
            assert.equal('EMAPNIK', err.code);
            assert.equal(err.message.split("'")[0], 'Failed to find font face ');
            done();
        });
    });
    it('does not error out if style references a registered font', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
            assert.ifError(err);
            done();
        });
    });
    it('errors out if style references a missing image', function(done) {
        tilelive.load('tm2z://' + path.join(fixtureDir, 'missing_image.tm2z'), function(err, source) {
            assert.equal('EMAPNIK', err.code);
            assert.equal(err.message.split(':')[0], 'file could not be found');
            done();
        });
    });
    it('profiles a tm2z file', function(done) {
        this.timeout(0);
        tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
            assert.ifError(err);
            source.profile(function(err, profile) {
                assert.ifError(err);
                assert.deepEqual([
                    'tiles',
                    'xmltime',
                    'drawtime',
                    'loadtime',
                    'srcbytes',
                    'imgbytes'
                ], Object.keys(profile));
                assert.equal('number', typeof profile.xmltime);
                assert.deepEqual(['avg','min','max'], Object.keys(profile.drawtime));
                assert.deepEqual(['avg','min','max'], Object.keys(profile.loadtime));
                assert.deepEqual(['avg','min','max'], Object.keys(profile.srcbytes));
                assert.deepEqual(['avg','min','max'], Object.keys(profile.imgbytes));
                assert.deepEqual([
                    '0/0/0',
                    '1/1/0',
                    '2/2/1',
                    '3/4/3',
                    '4/9/7',
                    '5/19/14',
                    '6/39/29',
                    '7/79/58',
                    '8/159/117',
                    '9/319/235',
                    '10/638/470',
                    '11/1276/940',
                    '12/2553/1880',
                    '13/5106/3761',
                    '14/10212/7522',
                    '15/20424/15045',
                    '16/40849/30091',
                    '17/81699/60182',
                    '18/163398/120364',
                    '19/326797/240728',
                    '20/653594/481456',
                    '21/1307188/962913',
                    '22/2614376/1925826'
                ], profile.tiles.map(function(t) { return t.z + '/' + t.x + '/' + t.y }));
                done();
            });
        });
    });
});

describe('tm2z+http', function() {
    it('loads a tm2z+http url', function(done) {
        this.timeout(5000);
        tilelive.load('tm2z+' + remotePath, function(err, source) {
            assert.ifError(err);
            done();
        });
    });
    it('matches expected xml', function(done) {
        this.timeout(5000);
        tilelive.load('tm2z+' + remotePath, function(err, source) {
            assert.ifError(err);
            assert.equal(xml, source._xml);
            done();
        });
    });
    it('errors out on an invalid S3 url', function(done) {
        tilelive.load('tm2z+http://mapbox.s3.amazonaws.com/tilelive-vector/invalid.tm2z', function(err, source) {
            assert.equal('Z_DATA_ERROR', err.code);
            done();
        });
    });
});
<|endoftext|>


<commit_before>/* eslint-env mocha */
'use strict';
process.env.PORT = 0;

require("coffee-script/register");
var Hubot = require('hubot');
var Path = require('path');
var should = require('should');

var adapterPath = Path.join(Path.dirname(require.resolve('hubot')), "src", "adapters");
var robot = Hubot.loadBot(adapterPath, "shell", true, "MochaHubot");

//var Helper = require('hubot-test-helper');
//var scriptHelper = new Helper('./scripts/hubot-jenkins-notifier.js')

var JenkinsNotifier = require('../scripts/hubot-jenkins-notifier.js');
var jenkinsNotifier = JenkinsNotifier(robot);
var JenkinsNotifierRequest = JenkinsNotifier.JenkinsNotifierRequest;

var commonBodies = {
  "FINISHED_FAILURE_fullURL": {
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": 1,
      "phase": "FINISHED",
      "status": "FAILURE",
      "url": "job/project name/5",
      "full_url": "http://ci.jenkins.org/job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
  "FINISHED_FAILURE": {
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": 1,
      "phase": "FINISHED",
      "status": "FAILURE",
      "url": "job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
  "FINISHED_SUCCESS": {
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": 1,
      "phase": "FINISHED",
      "status": "SUCCESS",
      "url": "job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
  "STARTED":{
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": 2,
      "phase": "STARTED",
      "url": "job/project name/5",
      "full_url": "http://ci.jenkins.org/job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
  "BAD_BAD_BAD": {
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": "non number",
      "phase": "BAD",
      "status": "BAD",
      "url": "job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
}

describe("JenkinsNotifier.shouldNotify", function() {
  /* TODO: add unknown status tests */
  describe("started job", function() {
    it("started job, previous job failed, and onStarted=S", function() {
      var notifier = new JenkinsNotifierRequest();
      notifier.setStatus("FAILURE");
      notifier.setQuery({onStart: 'S' });
      should(notifier.shouldNotify(commonBodies.STARTED)).be.false();
    });
    it("previous job failed, and onStarted=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onStart: 'F' });
        should(notifier.shouldNotify(commonBodies.STARTED)).be.true();
    });
    it("previous job success, and onStarted=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onStart: 'S' });
        should(notifier.shouldNotify(commonBodies.STARTED)).be.true();
    });
    it("previous job success, and onStarted=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onStart: 'F' });
        should(notifier.shouldNotify(commonBodies.STARTED)).be.false();
    });
  });
  describe("finished job - failure", function() {
    it("previous job failed, and onFinished=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onFinished: 'S' });
        should(notifier.shouldNotify(commonBodies.FINISHED_FAILURE)).be.false();
    });
    it("previous job failed, and onFinished=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onFinished: 'F' });
        should(notifier.shouldNotify(commonBodies.FINISHED_FAILURE)).be.true();
    });
    it("previous job success, and onFinished=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onFinished: 'S' });
        should(notifier.shouldNotify(commonBodies.FINISHED_FAILURE)).be.false();
    });
    it("previous job success, and onFinished=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onFinished: 'F' });
        should(notifier.shouldNotify(commonBodies.FINISHED_FAILURE)).be.true();
    });
  });
  describe("finished job - success", function() {
        it("previous job failed, and onFinished=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onFinished: 'S' });
        should(notifier.shouldNotify(commonBodies.FINISHED_SUCCESS)).be.true();
    });
    it("previous job failed, and onFinished=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onFinished: 'F' });
        should(notifier.shouldNotify(commonBodies.FINISHED_SUCCESS)).be.false();
    });
    it("previous job success, and onFinished=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onFinished: 'S' });
        should(notifier.shouldNotify(commonBodies.FINISHED_SUCCESS)).be.true();
    });
    it("previous job success, and onFinished=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onFinished: 'F' });
        should(notifier.shouldNotify(commonBodies.FINISHED_SUCCESS)).be.false();
    });
  });
});

describe("JenkinsNotifierRequest.buildEnvelope", function() {
  it("username and room should throw exception", function() {
    (function(){
      JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject(
        "/hubot/jenkins-notify?room=%23halkeye&user=someusername"
      ));
    }).should.throw();
  });
  it("always_notify", function() {
    var envelope = JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject("/hubot/jenkins-notify?room=%23halkeye&always_notify=1"));
    should(envelope).have.eql({
      onStart: '',
      onFinished: 'FS',
      user: { room: '#halkeye' },
      room: '#halkeye'
    });
  });
  it("notstrat", function() {
    var envelope = JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject("/hubot/jenkins-notify?room=%23halkeye&notstrat=FS"));
    should(envelope).have.eql({
      onStart: '',
      onFinished: 'FS',
      user: { room: '#halkeye' },
      room: '#halkeye'
    });
  });
  it("onStart", function() {
    var envelope = JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject("/hubot/jenkins-notify?room=%23halkeye&onStart=FS"));
    should(envelope).have.eql({
      onStart: 'FS',
      onFinished: '',
      user: { room: '#halkeye' },
      room: '#halkeye'
    });
  });
  it("onFinished", function() {
    var envelope = JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject("/hubot/jenkins-notify?room=%23halkeye&onFinished=FS"));
    should(envelope).have.eql({
      onStart: '',
      onFinished: 'FS',
      user: { room: '#halkeye' },
      room: '#halkeye'
    });
  });
});

describe("JenkinsNotifier", function() {
  Object.keys(commonBodies).forEach(function(field) {
    it(field + " generic template", function() {
      var res = {
        status: function(code) { this.code = code; return this; },
        end: function(msg) { this.msg = msg; return this; },
      };

      jenkinsNotifier.process({
        url: "/hubot/jenkins-notify?room=%23halkeye&onStart=FS&onFinished=FS",
        body: commonBodies.FINISHED_FAILURE
      }, res);

      should(res.code).have.eql(200);
      should(res.msg).have.eql('');
    });
  });
});

var test_data = [
  {
    "name": "finished-failed",
    "expected_out": ["JobName build #1 started failing: http://ci.jenkins.org/job/project name/5"],
    "body": commonBodies.FINISHED_FAILURE_fullURL
  }, {
    "name": "finished-failed-nofull_url",
    "expected_out": ["JobName build #1 started failing: job/project name/5"],
    "body": commonBodies.FINISHED_FAILURE
  }, {
    "name": "started",
    "expected_out": ["JobName build #2 started: http://ci.jenkins.org/job/project name/5"],
    "body": commonBodies.STARTED
  }, {
    "name": "started-with-previous-failed",
    "expected_out": ["JobName build #2 started: http://ci.jenkins.org/job/project name/5"],
    "previousBuildFailed": true,
    "body": commonBodies.STARTED
  }
];
test_data.forEach(function(test) {
  describe(test.name, function() {
    //after(function() { this.room.destroy(); })
    before(function() {
      //this.room = scriptHelper.createRoom();
      this.notifier = new JenkinsNotifierRequest();
      if (test.previousBuildFailed) {
        this.notifier.setStatus("FAILURE");
      }
      this.notifier.setQuery(JenkinsNotifierRequest.buildQueryObject(
        "/hubot/jenkins-notify?room=%23halkeye&onStart=FS&onFinished=FS"
      ));
      this.messages = this.notifier.process(test.body);
    });
    it('Robot sent out respond', function() {
      should(this.messages).have.eql(test.expected_out);
    });
  });
});
<commit_msg>more complete test coverage<commit_after>/* eslint-env mocha */
'use strict';
process.env.PORT = 0;

require("coffee-script/register");
var Hubot = require('hubot');
var Path = require('path');
var should = require('should');

var adapterPath = Path.join(Path.dirname(require.resolve('hubot')), "src", "adapters");
var robot = Hubot.loadBot(adapterPath, "shell", true, "MochaHubot");

//var Helper = require('hubot-test-helper');
//var scriptHelper = new Helper('./scripts/hubot-jenkins-notifier.js')

var JenkinsNotifier = require('../scripts/hubot-jenkins-notifier.js');
var jenkinsNotifier = JenkinsNotifier(robot);
var JenkinsNotifierRequest = JenkinsNotifier.JenkinsNotifierRequest;

var commonBodies = {
  "STARTED":{
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": 2,
      "phase": "STARTED",
      "url": "job/project name/5",
      "full_url": "http://ci.jenkins.org/job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
  "COMPLETED_SUCCESS":{
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      number: 69,
      queue_id: 69,
      phase: 'COMPLETED',
      status: 'SUCCESS',
      url: 'job/Jobname/69/',
      scm: {},
      log: 'Started by user admin\nNotifying endpoint \'HTTP:http://192.168.168.128:9001/hubot/jenkins-notify?room=general&always_notify=1&trace=1\'\nBuilding in workspace /var/jenkins_home/workspace/Jobname\n[Jobname] $ /bin/sh -xe /tmp/hudson5174919973359476640.sh\nNotifying endpoint \'HTTP:http://192.168.168.128:9001/hubot/jenkins-notify?room=general&always_notify=1&trace=1\'\n',
      artifacts: {}
    }
  },
  "COMPLETED_FAILURE":{
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      number: 70,
      queue_id: 70,
      phase: 'COMPLETED',
      status: 'FAILURE',
      url: 'job/Jobname/70/',
      scm: {},
      log: 'Started by user admin\nNotifying endpoint \'HTTP:http://192.168.168.128:9001/hubot/jenkins-notify?room=general&always_notify=1&trace=1\'\nBuilding in workspace /var/jenkins_home/workspace/Jobname\n[Jobname] $ /bin/sh -xe /tmp/hudson326640172349901710.sh\n+ fail and break this build!\n/tmp/hudson326640172349901710.sh: 3: /tmp/hudson326640172349901710.sh: fail: not found\nBuild step \'Execute shell\' marked build as failure\nNotifying endpoint \'HTTP:http://192.168.168.128:9001/hubot/jenkins-notify?room=general&always_notify=1&trace=1\'\n',
      artifacts: {}
    }
  },
  "FINALIZED_SUCCESS":{
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      number: 69,
      queue_id: 69,
      phase: 'FINALIZED',
      status: 'SUCCESS',
      url: 'job/Jobname/69/',
      scm: {},
      log: 'Started by user admin\nNotifying endpoint \'HTTP:http://192.168.168.128:9001/hubot/jenkins-notify?room=general&always_notify=1&trace=1\'\nBuilding in workspace /var/jenkins_home/workspace/Jobname\n[Jobname] $ /bin/sh -xe /tmp/hudson5174919973359476640.sh\nNotifying endpoint \'HTTP:http://192.168.168.128:9001/hubot/jenkins-notify?room=general&always_notify=1&trace=1\'\nFinished: SUCCESS\n',
      artifacts: {}
    }
  },
  "FINALIZED_FAILURE":{
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      number: 70,
      queue_id: 70,
      phase: 'FINALIZED',
      status: 'FAILURE',
      url: 'job/Jobname/70/',
      scm: {},
      log: 'Started by user admin\nNotifying endpoint \'HTTP:http://192.168.168.128:9001/hubot/jenkins-notify?room=general&always_notify=1&trace=1\'\nBuilding in workspace /var/jenkins_home/workspace/Jobname\n[Jobname] $ /bin/sh -xe /tmp/hudson326640172349901710.sh\n+ fail and break this build!\n/tmp/hudson326640172349901710.sh: 3: /tmp/hudson326640172349901710.sh: fail: not found\nBuild step \'Execute shell\' marked build as failure\nNotifying endpoint \'HTTP:http://192.168.168.128:9001/hubot/jenkins-notify?room=general&always_notify=1&trace=1\'\nFinished: FAILURE\n',
      artifacts: {}
    }
  },
  "FINISHED_FAILURE_fullURL": {
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": 1,
      "phase": "FINISHED",
      "status": "FAILURE",
      "url": "job/project name/5",
      "full_url": "http://ci.jenkins.org/job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
  "FINISHED_FAILURE": {
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": 1,
      "phase": "FINISHED",
      "status": "FAILURE",
      "url": "job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
  "FINISHED_SUCCESS": {
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": 1,
      "phase": "FINISHED",
      "status": "SUCCESS",
      "url": "job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
  "BAD_BAD_BAD": {
    "name": "JobName",
    "url": "JobUrl",
    "build": {
      "number": "non number",
      "phase": "BAD",
      "status": "BAD",
      "url": "job/project name/5",
      "parameters": {
        "branch": "master"
      }
    }
  },
}

describe("JenkinsNotifier.shouldNotify", function() {
  /* TODO: add unknown status tests */
  describe("started job", function() {
    it("started job, previous job failed, and onStarted=S", function() {
      var notifier = new JenkinsNotifierRequest();
      notifier.setStatus("FAILURE");
      notifier.setQuery({onStart: 'S' });
      should(notifier.shouldNotify(commonBodies.STARTED)).be.false();
    });
    it("previous job failed, and onStarted=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onStart: 'F' });
        should(notifier.shouldNotify(commonBodies.STARTED)).be.true();
    });
    it("previous job success, and onStarted=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onStart: 'S' });
        should(notifier.shouldNotify(commonBodies.STARTED)).be.true();
    });
    it("previous job success, and onStarted=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onStart: 'F' });
        should(notifier.shouldNotify(commonBodies.STARTED)).be.false();
    });
  });
  describe("finished job - failure", function() {
    it("previous job failed, and onFinished=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onFinished: 'S' });
        should(notifier.shouldNotify(commonBodies.FINISHED_FAILURE)).be.false();
    });
    it("previous job failed, and onFinished=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onFinished: 'F' });
        should(notifier.shouldNotify(commonBodies.FINISHED_FAILURE)).be.true();
    });
    it("previous job success, and onFinished=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onFinished: 'S' });
        should(notifier.shouldNotify(commonBodies.FINISHED_FAILURE)).be.false();
    });
    it("previous job success, and onFinished=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onFinished: 'F' });
        should(notifier.shouldNotify(commonBodies.FINISHED_FAILURE)).be.true();
    });
  });
  describe("finished job - success", function() {
        it("previous job failed, and onFinished=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onFinished: 'S' });
        should(notifier.shouldNotify(commonBodies.FINISHED_SUCCESS)).be.true();
    });
    it("previous job failed, and onFinished=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("FAILURE");
        notifier.setQuery({onFinished: 'F' });
        should(notifier.shouldNotify(commonBodies.FINISHED_SUCCESS)).be.false();
    });
    it("previous job success, and onFinished=S", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onFinished: 'S' });
        should(notifier.shouldNotify(commonBodies.FINISHED_SUCCESS)).be.true();
    });
    it("previous job success, and onFinished=F", function() {
        var notifier = new JenkinsNotifierRequest();
        notifier.setStatus("SUCCESS");
        notifier.setQuery({onFinished: 'F' });
        should(notifier.shouldNotify(commonBodies.FINISHED_SUCCESS)).be.false();
    });
  });
});

describe("JenkinsNotifierRequest.buildEnvelope", function() {
  it("username and room should throw exception", function() {
    (function(){
      JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject(
        "/hubot/jenkins-notify?room=%23halkeye&user=someusername"
      ));
    }).should.throw();
  });
  it("always_notify", function() {
    var envelope = JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject("/hubot/jenkins-notify?room=%23halkeye&always_notify=1"));
    should(envelope).have.eql({
      onStart: '',
      onFinished: 'FS',
      user: { room: '#halkeye' },
      room: '#halkeye'
    });
  });
  it("notstrat", function() {
    var envelope = JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject("/hubot/jenkins-notify?room=%23halkeye&notstrat=FS"));
    should(envelope).have.eql({
      onStart: '',
      onFinished: 'FS',
      user: { room: '#halkeye' },
      room: '#halkeye'
    });
  });
  it("onStart", function() {
    var envelope = JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject("/hubot/jenkins-notify?room=%23halkeye&onStart=FS"));
    should(envelope).have.eql({
      onStart: 'FS',
      onFinished: '',
      user: { room: '#halkeye' },
      room: '#halkeye'
    });
  });
  it("onFinished", function() {
    var envelope = JenkinsNotifierRequest.buildEnvelope(JenkinsNotifierRequest.buildQueryObject("/hubot/jenkins-notify?room=%23halkeye&onFinished=FS"));
    should(envelope).have.eql({
      onStart: '',
      onFinished: 'FS',
      user: { room: '#halkeye' },
      room: '#halkeye'
    });
  });
});

describe("JenkinsNotifier", function() {
  [null, ''].concat(Object.keys(commonBodies).map(function(field) {
    return commonBodies[field].build.status;
  })).forEach(function(oldState) {
    Object.keys(commonBodies).forEach(function(field) {
      it(field + " generic template", function() {
        var res = {
          status: function(code) { this.code = code; return this; },
          end: function(msg) { this.msg = msg; return this; },
        };

        jenkinsNotifier.statuses = {};
        jenkinsNotifier.statuses[commonBodies[field].name] = oldState;
        jenkinsNotifier.process({
          url: "/hubot/jenkins-notify?room=%23halkeye&onStart=FS&onFinished=FS",
          body: commonBodies[field]
        }, res);

        should(res.code).have.eql(200);
        should(res.msg).have.eql('');
      });
    });
  });
});

var test_data = [
  {
    "name": "finished-failed",
    "expected_out": ["JobName build #1 started failing: http://ci.jenkins.org/job/project name/5"],
    "body": commonBodies.FINISHED_FAILURE_fullURL
  }, {
    "name": "finished-failed-nofull_url",
    "expected_out": ["JobName build #1 started failing: job/project name/5"],
    "body": commonBodies.FINISHED_FAILURE
  }, {
    "name": "started",
    "expected_out": ["JobName build #2 started: http://ci.jenkins.org/job/project name/5"],
    "body": commonBodies.STARTED
  }, {
    "name": "started-with-previous-failed",
    "expected_out": ["JobName build #2 started: http://ci.jenkins.org/job/project name/5"],
    "previousBuildFailed": true,
    "body": commonBodies.STARTED
  }
];
test_data.forEach(function(test) {
  describe(test.name, function() {
    //after(function() { this.room.destroy(); })
    before(function() {
      //this.room = scriptHelper.createRoom();
      this.notifier = new JenkinsNotifierRequest();
      if (test.previousBuildFailed) {
        this.notifier.setStatus("FAILURE");
      }
      this.notifier.setQuery(JenkinsNotifierRequest.buildQueryObject(
        "/hubot/jenkins-notify?room=%23halkeye&onStart=FS&onFinished=FS"
      ));
      this.messages = this.notifier.process(test.body);
    });
    it('Robot sent out respond', function() {
      should(this.messages).have.eql(test.expected_out);
    });
  });
});
<|endoftext|>


<commit_before>'use strict';

var path  = require('path')
  , ee    = require('event-emitter')
  , watch = require('./watch').watch

  , basename = path.basename, dirname = path.dirname, join = path.join
  , resolve = path.resolve

  , Watcher;

Watcher = function (path) {
	this.path = path;
	this.missing = [];
	this.onchange = this.onchange.bind(this);
	this.onremove = this.onremove.bind(this);
	this.up = this.up.bind(this);
	this.watch();
	this.emitter = ee();
	this.emitter.close = this.close.bind(this);
	return this.emitter;
};

Watcher.prototype = {
	close: function () {
		this.watcher.close();
	},
	up: function () {
		var parent = dirname(this.path);
		if (parent === this.path) {
			return;
		}
		this.missing.unshift(basename(this.path));
		this.path = parent;
		this.watch();
	},
	watch: function () {
		var watcher;
		try {
			watcher = watch(this.path);
		} catch (e) {
			this.up();
			return;
		}
		this.onwatch(watcher);
	},
	tryDown: function () {
		var current = this.path, watcher, promise, npath;
		npath = join(this.path, this.missing[0]);
		try {
			watcher = watch(npath);
		} catch (e) {
			return false;
		}
		this.path = npath;
		this.missing.shift();
		if (!this.missing.length) {
			this.onwatch(watcher);
			this.oncreate();
		} else if (!this.tryDown()) {
			this.onwatch(watcher);
		} else {
			watcher.close();
		}
		return true;
	},
	onwatch: function (watcher) {
		if (!this.missing.length) {
			watcher.on('change', this.onchange);
			watcher.once('end', this.onremove);
		} else {
			watcher.on('change', function () {
				if (this.tryDown()) {
					watcher.close();
				}
			}.bind(this));
			watcher.once('end', this.up);
		}
		this.watcher = watcher;
	},
	oncreate: function () {
		this.emitter.emit('change', { type: 'create' });
	},
	onchange: function () {
		this.emitter.emit('change', { type: 'modify' });
	},
	onremove: function () {
		this.emitter.emit('change', { type: 'remove' });
		this.up();
	}
};

module.exports = exports = function (path) {
	return new Watcher(resolve(String(path)));
};
exports.WatchPath = Watcher;
<commit_msg>Convention cleanup<commit_after>'use strict';

var ee    = require('event-emitter')
  , path  = require('path')
  , watch = require('./watch').watch

  , basename = path.basename, dirname = path.dirname, join = path.join
  , resolve = path.resolve

  , Watcher;

Watcher = function (path) {
	this.path = path;
	this.missing = [];
	this.onchange = this.onchange.bind(this);
	this.onremove = this.onremove.bind(this);
	this.up = this.up.bind(this);
	this.watch();
	this.emitter = ee();
	this.emitter.close = this.close.bind(this);
	return this.emitter;
};

Watcher.prototype = {
	close: function () {
		this.watcher.close();
	},
	up: function () {
		var parent = dirname(this.path);
		if (parent === this.path) {
			return;
		}
		this.missing.unshift(basename(this.path));
		this.path = parent;
		this.watch();
	},
	watch: function () {
		var watcher;
		try {
			watcher = watch(this.path);
		} catch (e) {
			this.up();
			return;
		}
		this.onwatch(watcher);
	},
	tryDown: function () {
		var current = this.path, watcher, promise, npath;
		npath = join(this.path, this.missing[0]);
		try {
			watcher = watch(npath);
		} catch (e) {
			return false;
		}
		this.path = npath;
		this.missing.shift();
		if (!this.missing.length) {
			this.onwatch(watcher);
			this.oncreate();
		} else if (!this.tryDown()) {
			this.onwatch(watcher);
		} else {
			watcher.close();
		}
		return true;
	},
	onwatch: function (watcher) {
		if (!this.missing.length) {
			watcher.on('change', this.onchange);
			watcher.once('end', this.onremove);
		} else {
			watcher.on('change', function () {
				if (this.tryDown()) {
					watcher.close();
				}
			}.bind(this));
			watcher.once('end', this.up);
		}
		this.watcher = watcher;
	},
	oncreate: function () {
		this.emitter.emit('change', { type: 'create' });
	},
	onchange: function () {
		this.emitter.emit('change', { type: 'modify' });
	},
	onremove: function () {
		this.emitter.emit('change', { type: 'remove' });
		this.up();
	}
};

module.exports = exports = function (path) {
	return new Watcher(resolve(String(path)));
};
exports.WatchPath = Watcher;
<|endoftext|>


<commit_before>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        if (fileContentReadme.indexOf('## License') === -1) {
            console.log('Warning: The README.md should have a section ## License');
            console.log();
        }
        if (fileContentReadme.indexOf('## Changelog') === -1) {
            console.log('Warning: The README.md should have a section ## Changelog');
            console.log();
        }
        done();
    });
});
<commit_msg>update basic package-file testing<commit_after>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        var licenseFileExists = fs.existsSync(__dirname + '/../LICENSE');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        if (fileContentReadme.indexOf('## Changelog') === -1) {
            console.log('Warning: The README.md should have a section ## Changelog');
            console.log();
        }
        expect((licenseFileExists || fileContentReadme.indexOf('## License') !== -1), 'A LICENSE must exist as LICENSE file or as part of the README.md').to.be.true;
        if (!licenseFileExists) {
            console.log('Warning: The License should also exist as LICENSE file');
            console.log();
        }
        if (fileContentReadme.indexOf('## License') === -1) {
            console.log('Warning: The README.md should also have a section ## License to be shown in Admin3');
            console.log();
        }
        done();
    });
});
<|endoftext|>


<commit_before>var test = require('tape');
var tilelive = require('tilelive');
var TileJSON = require('tilejson');
var url = require('url');
var assert = require('assert');
var path = require('path');
var fs = require('fs');
var crypto = require('crypto');
var Vector = require('..');

function md5(str) {
    return crypto.createHash('md5').update(str).digest('hex');
}

// skip tests that require s3 authentication if necessary
// use ~$ TILELIVE_VECTOR_NO_AUTH=true npm test
var TILELIVE_VECTOR_NO_AUTH = (process.env.TILELIVE_VECTOR_NO_AUTH) ? process.env.TILELIVE_VECTOR_NO_AUTH : false;

// Load fixture data.
var fixtureDir = path.resolve(__dirname, 'fixtures', 'tm2z'),
    remotePath = 'http://mapbox.s3.amazonaws.com/tilelive-vector/test-tm2z.tm2z',
    xml = fs.readFileSync(path.join(fixtureDir, 'project', 'project.xml'), 'utf8');

// Register vector:, tm2z:, tm2z+http: and mapbox: tilelive protocols
Vector.registerProtocols(tilelive);
tilelive.protocols['mapbox:'] = function Source(uri, callback) {
    var MapboxAccessToken = process.env.MapboxAccessToken;
    if (!MapboxAccessToken) return callback(new Error('env var MapboxAccessToken is required'));
    return new TileJSON('http://a.tiles.mapbox.com/v4' + uri.pathname + '.json?access_token=' + MapboxAccessToken, callback);
};

// Register font
Vector.mapnik.register_fonts(path.join(__dirname, 'fonts', 'source-sans-pro'));

['cold', 'warm'].forEach(function(label) {
    test(label + ': tm2z+http content length error', function(assert) {
        var server = require('http').createServer(function(req, res) {
            var buffer = fs.readFileSync(path.join(fixtureDir, 'patternstyle.tm2z'));
            res.setHeader('content-length', buffer.length);
            res.writeHead(200);
            res.write(buffer.slice(0,250e3));
            req.socket.destroy();
        });
        server.listen(9191, afterListen);
        function afterListen(err) {
            assert.ifError(err);
            tilelive.load('tm2z+http://127.0.0.1:9191/patternstyle.tm2z', function(err, source) {
                assert.ok(err, 'has error');
                assert.equal(err.code, undefined, 'not a mapnik error');
                server.close(afterClose);
            });
        }
        function afterClose(err) {
            assert.ifError(err);
            assert.end();
        }
    });
});

test('tm2z+http ENOTFOUND', function(assert) {
    tilelive.load('tm2z+http://not-a-valid-domain/patternstyle.tm2z', function(err, source) {
        assert.ok(err, 'has error');
        assert.equal(err.code, 'ENOTFOUND', 'code: ENOTFOUND');
        assert.end();
    });
});

test('exposes the mapnik binding', function(t) {
    t.ok(Vector.mapnik);
    t.end();
});
test('direct load (string uri)', function(t) {
    Vector.tm2z('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('direct load (object uri)', function(t) {
    Vector.tm2z({ protocol:'tm2z:', pathname: path.join(fixtureDir, 'project.tm2z') }, function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('loads a tm2z url', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('loads a tm2z url once', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'doublecall.tm2z'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('matches expected xml', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
        t.ifError(err);
        t.equal(source._xml, xml);
        t.end();
    });
});
test('gunzips then untars', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tar.gz'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('errors out if not gzipped', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tar'), function(err, source) {
        t.equal(err.code, 'Z_DATA_ERROR');
        t.equal(err.message, 'incorrect header check');
        t.end();
    });
});
test('errors out on bad gunzip', function(t) {
   tilelive.load('tm2z://' + path.join(fixtureDir, 'doublezip.tm2z'), function(err, source) {
        t.equal(err.message, 'invalid tar file');
        t.end();
    });
});
test('errors out if file size exceeds max size', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'filesize.tm2z'), function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Upload size should not exceed 750KB.');
        t.end();
    });
});
test('errors out if file size exceeds custom max size', function(t) {
    tilelive.load({
        protocol: 'tm2z:',
        pathname: path.join(fixtureDir, 'filesize.tm2z'),
        filesize: 500 * 1024
    }, function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Upload size should not exceed 500KB.');
        t.end();
    });
});
test('errors out if unzipped size exceeds max size', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'gunzipsize.tm2z'), function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Unzipped size should not exceed 5MB.');
        t.end();
    });
});
test('errors out if unzipped size exceeds custom max size', function(t) {
    tilelive.load({
        protocol: 'tm2z:',
        pathname: path.join(fixtureDir, 'gunzipsize.tm2z'),
        gunzipsize: 1024 * 1024
    }, function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Unzipped size should not exceed 1MB.');
        t.end();
    });
});
test('errors out if unzipped project.xml size exceeds max size', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'xmlsize.tm2z'), function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Unzipped project.xml size should not exceed 750KB.');
        t.end();
    });
});
test('errors out if unzipped project.xml size exceeds custom max size', function(t) {
    tilelive.load({
        protocol: 'tm2z:',
        pathname: path.join(fixtureDir, 'xmlsize.tm2z'),
        xmlsize: 300 * 1024
    }, function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Unzipped project.xml size should not exceed 300KB.');
        t.end();
    });
});
test('errors out if not a directory', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'nodirectory.tm2z'), function(err, source) {
        t.equal(err.message.split(',')[0], 'EISDIR');
        t.end();
    });
});
test('errors out if missing project.xml', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'empty.tm2z'), function(err, source) {
        t.equal(err.message, 'project.xml not found in package');
        t.end();
    });
});
test('errors out on invalid project.xml', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'malformed.tm2z'), function(err, source) {
        t.equal('EMAPNIK', err.code);
        // err.message on windows is completely different
        //assert(err.message.split(':')[0], 'expected < at line 1');
        t.end();
    });
});
test('errors out if style references a missing font', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'missing_font.tm2z'), function(err, source) {
        t.equal('EMAPNIK', err.code);
        t.equal(err.message.split("'")[0], 'Failed to find font face ');
        t.end();
    });
});
test('does not error out if style references a registered font', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('errors out if style references a missing image', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'missing_image.tm2z'), function(err, source) {
        t.equal('EMAPNIK', err.code);
        t.equal(err.message.split(':')[0], 'file could not be found');
        t.end();
    });
});
test('errors out if style causes parse error', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'invalid_parsecolor.tm2z'), function(err, source) {
        source.getTile(3, 4, 3, function(err, run1, headers) {
            t.equal('EMAPNIK', err.code);
            t.equal(err.message.split(':')[0], 'Failed to parse color');
            t.end();
        });
    });
});
test.only('profiles a tm2z file', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project-v6.tm2z'), function(err, source) {
        t.ifError(err);
        source.profile(function(err, profile) {
            t.ifError(err);
            t.deepEqual([
                'tiles',
                'xmltime',
                'drawtime',
                'loadtime',
                'srcbytes',
                'imgbytes'
            ], Object.keys(profile));
            t.equal('number', typeof profile.xmltime);
            t.deepEqual(['avg','min','max'], Object.keys(profile.drawtime));
            t.deepEqual(['avg','min','max'], Object.keys(profile.loadtime));
            t.deepEqual(['avg','min','max'], Object.keys(profile.srcbytes));
            t.deepEqual(['avg','min','max'], Object.keys(profile.imgbytes));
            t.deepEqual([
                '0/0/0',
                '1/1/0',
                '2/2/1',
                '3/4/3',
                '4/9/7',
                '5/19/14',
                '6/39/29',
                '7/79/58',
                '8/159/117',
                '9/319/235',
                '10/638/470',
                '11/1276/940',
                '12/2553/1880',
                '13/5106/3761',
                '14/10212/7522',
                '15/20424/15045',
                '16/40849/30091',
                '17/81699/60182',
                '18/163398/120364',
                '19/326797/240728',
                '20/653594/481456',
                '21/1307188/962913',
                '22/2614376/1925826'
            ], profile.tiles.map(function(t) { return t.z + '/' + t.x + '/' + t.y }));
            t.end();
        });
    });
});

test('loads a tm2z+http url', function(t) {
    tilelive.load('tm2z+' + remotePath, function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('matches expected xml', function(t) {
    tilelive.load('tm2z+' + remotePath, function(err, source) {
        t.ifError(err);
        t.equal(xml, source._xml);
        t.end();
    });
});
test('errors out on an invalid S3 url', function(t) {
    tilelive.load('tm2z+http://mapbox.s3.amazonaws.com/tilelive-vector/invalid.tm2z', function(err, source) {
        t.equal('Z_DATA_ERROR', err.code);
        t.end();
    });
});

test('errors out on private object with tm2z+http protocol', {skip: TILELIVE_VECTOR_NO_AUTH}, function(t) {
    tilelive.load('tm2z+http://mapbox.s3.amazonaws.com/tilelive-vector/test-tm2z-private.tm2z', function(err, source) {
        t.equal('Z_DATA_ERROR', err.code);
        t.end();
    });
});

test('load private tm2z from s3 using tm2z+s3 protocol', {skip: TILELIVE_VECTOR_NO_AUTH}, function(t) {
    tilelive.load('tm2z+s3://mapbox/tilelive-vector/test-tm2z-private.tm2z', function(err, source) {
        t.ifError(err);
        t.end();
    });
});

test('errors out on tm2z file on s3 where we do not have access', {skip: TILELIVE_VECTOR_NO_AUTH}, function(t) {
    tilelive.load('tm2z+s3://example/does-not-exist.tm2z', function(err, source) {
        t.equal(err.code, 'AccessDenied');
        t.end();
    });
});
<commit_msg>revert testing change<commit_after>var test = require('tape');
var tilelive = require('tilelive');
var TileJSON = require('tilejson');
var url = require('url');
var assert = require('assert');
var path = require('path');
var fs = require('fs');
var crypto = require('crypto');
var Vector = require('..');

function md5(str) {
    return crypto.createHash('md5').update(str).digest('hex');
}

// skip tests that require s3 authentication if necessary
// use ~$ TILELIVE_VECTOR_NO_AUTH=true npm test
var TILELIVE_VECTOR_NO_AUTH = (process.env.TILELIVE_VECTOR_NO_AUTH) ? process.env.TILELIVE_VECTOR_NO_AUTH : false;

// Load fixture data.
var fixtureDir = path.resolve(__dirname, 'fixtures', 'tm2z'),
    remotePath = 'http://mapbox.s3.amazonaws.com/tilelive-vector/test-tm2z.tm2z',
    xml = fs.readFileSync(path.join(fixtureDir, 'project', 'project.xml'), 'utf8');

// Register vector:, tm2z:, tm2z+http: and mapbox: tilelive protocols
Vector.registerProtocols(tilelive);
tilelive.protocols['mapbox:'] = function Source(uri, callback) {
    var MapboxAccessToken = process.env.MapboxAccessToken;
    if (!MapboxAccessToken) return callback(new Error('env var MapboxAccessToken is required'));
    return new TileJSON('http://a.tiles.mapbox.com/v4' + uri.pathname + '.json?access_token=' + MapboxAccessToken, callback);
};

// Register font
Vector.mapnik.register_fonts(path.join(__dirname, 'fonts', 'source-sans-pro'));

['cold', 'warm'].forEach(function(label) {
    test(label + ': tm2z+http content length error', function(assert) {
        var server = require('http').createServer(function(req, res) {
            var buffer = fs.readFileSync(path.join(fixtureDir, 'patternstyle.tm2z'));
            res.setHeader('content-length', buffer.length);
            res.writeHead(200);
            res.write(buffer.slice(0,250e3));
            req.socket.destroy();
        });
        server.listen(9191, afterListen);
        function afterListen(err) {
            assert.ifError(err);
            tilelive.load('tm2z+http://127.0.0.1:9191/patternstyle.tm2z', function(err, source) {
                assert.ok(err, 'has error');
                assert.equal(err.code, undefined, 'not a mapnik error');
                server.close(afterClose);
            });
        }
        function afterClose(err) {
            assert.ifError(err);
            assert.end();
        }
    });
});

test('tm2z+http ENOTFOUND', function(assert) {
    tilelive.load('tm2z+http://not-a-valid-domain/patternstyle.tm2z', function(err, source) {
        assert.ok(err, 'has error');
        assert.equal(err.code, 'ENOTFOUND', 'code: ENOTFOUND');
        assert.end();
    });
});

test('exposes the mapnik binding', function(t) {
    t.ok(Vector.mapnik);
    t.end();
});
test('direct load (string uri)', function(t) {
    Vector.tm2z('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('direct load (object uri)', function(t) {
    Vector.tm2z({ protocol:'tm2z:', pathname: path.join(fixtureDir, 'project.tm2z') }, function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('loads a tm2z url', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('loads a tm2z url once', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'doublecall.tm2z'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('matches expected xml', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
        t.ifError(err);
        t.equal(source._xml, xml);
        t.end();
    });
});
test('gunzips then untars', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tar.gz'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('errors out if not gzipped', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tar'), function(err, source) {
        t.equal(err.code, 'Z_DATA_ERROR');
        t.equal(err.message, 'incorrect header check');
        t.end();
    });
});
test('errors out on bad gunzip', function(t) {
   tilelive.load('tm2z://' + path.join(fixtureDir, 'doublezip.tm2z'), function(err, source) {
        t.equal(err.message, 'invalid tar file');
        t.end();
    });
});
test('errors out if file size exceeds max size', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'filesize.tm2z'), function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Upload size should not exceed 750KB.');
        t.end();
    });
});
test('errors out if file size exceeds custom max size', function(t) {
    tilelive.load({
        protocol: 'tm2z:',
        pathname: path.join(fixtureDir, 'filesize.tm2z'),
        filesize: 500 * 1024
    }, function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Upload size should not exceed 500KB.');
        t.end();
    });
});
test('errors out if unzipped size exceeds max size', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'gunzipsize.tm2z'), function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Unzipped size should not exceed 5MB.');
        t.end();
    });
});
test('errors out if unzipped size exceeds custom max size', function(t) {
    tilelive.load({
        protocol: 'tm2z:',
        pathname: path.join(fixtureDir, 'gunzipsize.tm2z'),
        gunzipsize: 1024 * 1024
    }, function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Unzipped size should not exceed 1MB.');
        t.end();
    });
});
test('errors out if unzipped project.xml size exceeds max size', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'xmlsize.tm2z'), function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Unzipped project.xml size should not exceed 750KB.');
        t.end();
    });
});
test('errors out if unzipped project.xml size exceeds custom max size', function(t) {
    tilelive.load({
        protocol: 'tm2z:',
        pathname: path.join(fixtureDir, 'xmlsize.tm2z'),
        xmlsize: 300 * 1024
    }, function(err, source) {
        t.equal(err instanceof RangeError, true);
        t.equal(err.message, 'Unzipped project.xml size should not exceed 300KB.');
        t.end();
    });
});
test('errors out if not a directory', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'nodirectory.tm2z'), function(err, source) {
        t.equal(err.message.split(',')[0], 'EISDIR');
        t.end();
    });
});
test('errors out if missing project.xml', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'empty.tm2z'), function(err, source) {
        t.equal(err.message, 'project.xml not found in package');
        t.end();
    });
});
test('errors out on invalid project.xml', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'malformed.tm2z'), function(err, source) {
        t.equal('EMAPNIK', err.code);
        // err.message on windows is completely different
        //assert(err.message.split(':')[0], 'expected < at line 1');
        t.end();
    });
});
test('errors out if style references a missing font', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'missing_font.tm2z'), function(err, source) {
        t.equal('EMAPNIK', err.code);
        t.equal(err.message.split("'")[0], 'Failed to find font face ');
        t.end();
    });
});
test('does not error out if style references a registered font', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project.tm2z'), function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('errors out if style references a missing image', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'missing_image.tm2z'), function(err, source) {
        t.equal('EMAPNIK', err.code);
        t.equal(err.message.split(':')[0], 'file could not be found');
        t.end();
    });
});
test('errors out if style causes parse error', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'invalid_parsecolor.tm2z'), function(err, source) {
        source.getTile(3, 4, 3, function(err, run1, headers) {
            t.equal('EMAPNIK', err.code);
            t.equal(err.message.split(':')[0], 'Failed to parse color');
            t.end();
        });
    });
});
test('profiles a tm2z file', function(t) {
    tilelive.load('tm2z://' + path.join(fixtureDir, 'project-v6.tm2z'), function(err, source) {
        t.ifError(err);
        source.profile(function(err, profile) {
            t.ifError(err);
            t.deepEqual([
                'tiles',
                'xmltime',
                'drawtime',
                'loadtime',
                'srcbytes',
                'imgbytes'
            ], Object.keys(profile));
            t.equal('number', typeof profile.xmltime);
            t.deepEqual(['avg','min','max'], Object.keys(profile.drawtime));
            t.deepEqual(['avg','min','max'], Object.keys(profile.loadtime));
            t.deepEqual(['avg','min','max'], Object.keys(profile.srcbytes));
            t.deepEqual(['avg','min','max'], Object.keys(profile.imgbytes));
            t.deepEqual([
                '0/0/0',
                '1/1/0',
                '2/2/1',
                '3/4/3',
                '4/9/7',
                '5/19/14',
                '6/39/29',
                '7/79/58',
                '8/159/117',
                '9/319/235',
                '10/638/470',
                '11/1276/940',
                '12/2553/1880',
                '13/5106/3761',
                '14/10212/7522',
                '15/20424/15045',
                '16/40849/30091',
                '17/81699/60182',
                '18/163398/120364',
                '19/326797/240728',
                '20/653594/481456',
                '21/1307188/962913',
                '22/2614376/1925826'
            ], profile.tiles.map(function(t) { return t.z + '/' + t.x + '/' + t.y }));
            t.end();
        });
    });
});

test('loads a tm2z+http url', function(t) {
    tilelive.load('tm2z+' + remotePath, function(err, source) {
        t.ifError(err);
        t.end();
    });
});
test('matches expected xml', function(t) {
    tilelive.load('tm2z+' + remotePath, function(err, source) {
        t.ifError(err);
        t.equal(xml, source._xml);
        t.end();
    });
});
test('errors out on an invalid S3 url', function(t) {
    tilelive.load('tm2z+http://mapbox.s3.amazonaws.com/tilelive-vector/invalid.tm2z', function(err, source) {
        t.equal('Z_DATA_ERROR', err.code);
        t.end();
    });
});

test('errors out on private object with tm2z+http protocol', {skip: TILELIVE_VECTOR_NO_AUTH}, function(t) {
    tilelive.load('tm2z+http://mapbox.s3.amazonaws.com/tilelive-vector/test-tm2z-private.tm2z', function(err, source) {
        t.equal('Z_DATA_ERROR', err.code);
        t.end();
    });
});

test('load private tm2z from s3 using tm2z+s3 protocol', {skip: TILELIVE_VECTOR_NO_AUTH}, function(t) {
    tilelive.load('tm2z+s3://mapbox/tilelive-vector/test-tm2z-private.tm2z', function(err, source) {
        t.ifError(err);
        t.end();
    });
});

test('errors out on tm2z file on s3 where we do not have access', {skip: TILELIVE_VECTOR_NO_AUTH}, function(t) {
    tilelive.load('tm2z+s3://example/does-not-exist.tm2z', function(err, source) {
        t.equal(err.code, 'AccessDenied');
        t.end();
    });
});
<|endoftext|>


<commit_before>import { computed } from '@ember/object';
import { inject as service } from '@ember/service';
import { Ability } from 'ember-can';

export default Ability.extend({
  currentUser: service(),

  canSource: computed('currentUser.role_id', function() {
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true;
      default:
        return false;
    }
  }),

  canDelete: computed('currentUser.role_id', function() {
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true;
      case 'provider_admin':
        return true;
      default:
        return false;
    }
  }),
  canCreate: computed('currentUser.role_id', 'currentUser.provider_id', 'currentUser.client_id', 'model.id', 'model.provider.id', function() {
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true
      case 'provider_admin':
        // direct_admins and consortium organizations should be able to create
        // consortium members should not
        return this.get('model.provider.memberType') == 'consortium_organization' || this.get('model.provider.memberType') == 'direct_member';
      default:
        return false;
    }
  }),
  canUpdate: computed('currentUser.role_id', 'currentUser.provider_id', 'currentUser.client_id', 'model.id', 'model.provider.id', 'model.provider.consortium.id', function() {
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true;
      case 'provider_admin':
        return this.get('currentUser.provider_id') === this.get('model.provider.id') || (this.get('model.provider.memberType') === 'consortium_organization' && this.get('currentUser.provider_id') === this.get('model.provider.consortium.id'));
      case 'client_admin':
        return this.get('currentUser.client_id') === this.get('model.id');
      default:
        return false
    }
  }),
  canRead: computed('currentUser.role_id', 'currentUser.provider_id', 'currentUser.client_id', 'model.id', 'model.provider.id', 'model.provider.consortium.id', function() {
    this.get('currentUser.role_id');
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true;
      case 'provider_admin':
        console.debug(this.get('currentUser.provider_id'));
        console.debug(this.get('model.provider.id'));
        console.debug(this.get('model.provider.memberType'));
        console.debug(this.get('model.provider.consortium.id'));
        return this.get('currentUser.provider_id') === this.get('model.provider.id') || (this.get('model.provider.memberType') === 'consortium_organization' && this.get('currentUser.provider_id') === this.get('model.provider.consortium.id'));
      case 'client_admin':
        return this.get('currentUser.client_id') === this.get('model.id');
      default:
        return false
    }
  })
});
<commit_msg>Remove accidental debug code<commit_after>import { computed } from '@ember/object';
import { inject as service } from '@ember/service';
import { Ability } from 'ember-can';

export default Ability.extend({
  currentUser: service(),

  canSource: computed('currentUser.role_id', function() {
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true;
      default:
        return false;
    }
  }),

  canDelete: computed('currentUser.role_id', function() {
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true;
      case 'provider_admin':
        return true;
      default:
        return false;
    }
  }),
  canCreate: computed('currentUser.role_id', 'currentUser.provider_id', 'currentUser.client_id', 'model.id', 'model.provider.id', function() {
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true
      case 'provider_admin':
        // direct_admins and consortium organizations should be able to create
        // consortium members should not
        return this.get('model.provider.memberType') == 'consortium_organization' || this.get('model.provider.memberType') == 'direct_member';
      default:
        return false;
    }
  }),
  canUpdate: computed('currentUser.role_id', 'currentUser.provider_id', 'currentUser.client_id', 'model.id', 'model.provider.id', 'model.provider.consortium.id', function() {
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true;
      case 'provider_admin':
        return this.get('currentUser.provider_id') === this.get('model.provider.id') || (this.get('model.provider.memberType') === 'consortium_organization' && this.get('currentUser.provider_id') === this.get('model.provider.consortium.id'));
      case 'client_admin':
        return this.get('currentUser.client_id') === this.get('model.id');
      default:
        return false
    }
  }),
  canRead: computed('currentUser.role_id', 'currentUser.provider_id', 'currentUser.client_id', 'model.id', 'model.provider.id', 'model.provider.consortium.id', function() {
    this.get('currentUser.role_id');
    switch(this.get('currentUser.role_id')) {
      case 'staff_admin':
        return true;
      case 'provider_admin':
        return this.get('currentUser.provider_id') === this.get('model.provider.id') || (this.get('model.provider.memberType') === 'consortium_organization' && this.get('currentUser.provider_id') === this.get('model.provider.consortium.id'));
      case 'client_admin':
        return this.get('currentUser.client_id') === this.get('model.id');
      default:
        return false
    }
  })
});
<|endoftext|>


<commit_before>const timeoutOverride = process.env.TEST_TIMEOUT_OVERRIDE

module.exports.command = function (selector, text, timeout) {
  const finalTimeout = timeout && timeout > 0 ? timeout : (timeoutOverride ? timeoutOverride : 5000)
  this.expect.element(selector).text.to.contain(text).before(finalTimeout)

  return this
}
<commit_msg>Update waitForElementWithText.js<commit_after>const timeoutOverride = process.env.TEST_TIMEOUT_OVERRIDE

module.exports.command = function (selector, text, timeout) {
  const finalTimeout = timeout && timeout > 0 ? timeout : (timeoutOverride ? timeoutOverride : 5000)
  this.expect.element(selector).text.to.contain(text).before(finalTimeout)

  return this
}
<|endoftext|>


<commit_before>import test from 'ava';
import jsdom from 'jsdom';
import whenDomReady from '../';

test('callback fires with global window', async t => {
	t.plan(1);
	whenDomReady(() => t.pass());
});

test('Promise resolves with global window', async t => {
	t.plan(1);
	whenDomReady().then(() => t.pass());
});

test('callback fires with local document', async t => {
	t.plan(1);
	const config = {
		html: '',
		onload: window => whenDomReady(() => t.pass(), window.document)
	};
	jsdom.env(config);
});

test.cb('Promise resolves with local document', t => {
	t.plan(1);
	const config = {
		html: '',
		onload: window => whenDomReady(window.document).then(() => {
			t.pass();
			t.end();
		})
	};
	jsdom.env(config);
});

test('callback fires if we wait for DOMContentLoaded', async t => {
	t.plan(1);
	const config = {
		html: '',
		created: (err, window) => whenDomReady(() => t.pass(), window.document)
	};
	jsdom.env(config);
});

test.cb('Promise resolves if we wait for DOMContentLoaded', t => {
	t.plan(1);
	const config = {
		html: '',
		created: (err, window) => whenDomReady(window.document).then(() => {
			t.pass();
			t.end();
		})
	};
	jsdom.env(config);
});
<commit_msg>Test Promise chain helper passes value through<commit_after>import test from 'ava';
import jsdom from 'jsdom';
import whenDomReady from '../';

test('callback fires with global window', async t => {
	t.plan(1);
	whenDomReady(() => t.pass());
});

test('Promise resolves with global window', async t => {
	t.plan(1);
	whenDomReady().then(() => t.pass());
});

test('callback fires with local document', async t => {
	t.plan(1);
	const config = {
		html: '',
		onload: window => whenDomReady(() => t.pass(), window.document)
	};
	jsdom.env(config);
});

test.cb('Promise resolves with local document', t => {
	t.plan(1);
	const config = {
		html: '',
		onload: window => whenDomReady(window.document).then(() => {
			t.pass();
			t.end();
		})
	};
	jsdom.env(config);
});

test('callback fires if we wait for DOMContentLoaded', async t => {
	t.plan(1);
	const config = {
		html: '',
		created: (err, window) => whenDomReady(() => t.pass(), window.document)
	};
	jsdom.env(config);
});

test.cb('Promise resolves if we wait for DOMContentLoaded', t => {
	t.plan(1);
	const config = {
		html: '',
		created: (err, window) => whenDomReady(window.document).then(() => {
			t.pass();
			t.end();
		})
	};
	jsdom.env(config);
});

test('Promise chain helper passes value through', async t => {
	t.plan(1);
	await Promise
		.resolve('foo')
		.then(whenDomReady.resume())
		.then(val => t.is(val, 'foo'));
});
<|endoftext|>