<commit_before>'use strict';

var grunt = require('grunt');
var path = require('path');
grunt.util = grunt.util || grunt.utils;

// Node v0.6 compat
path.sep = path.sep || path.normalize('/');

// In case the grunt being used to test is different than the grunt being
// tested, initialize the task and config subsystems.
if (grunt.task.searchDirs.length === 0) {
  grunt.task.init([]);
  grunt.config.init({});
}

// Where our fixtures are
var fixtures = path.join(__dirname, '..', 'fixtures');

// If verbose flag set, display output
var verboseLog = function() {};
if (grunt.util._.indexOf(process.argv, '-v') !== -1) {
  verboseLog = function() { console.log.apply(null, arguments); };
}

// helper for creating assertTasks for testing tasks in child processes
function assertTask(task, options) {
  var spawn = require('child_process').spawn;
  task = task || 'default';
  options = options || {};

  // get next/kill process trigger
  var trigger = options.trigger || 'Waiting...';
  delete options.trigger;

  // CWD to spawn
  var cwd = options.cwd || process.cwd();
  delete options.cwd;

  // Use grunt this process uses
  var spawnOptions = [process.argv[1]];
  // Turn options into spawn options
  grunt.util._.each(options, function(val, key) {
    spawnOptions.push('--' + key);
    spawnOptions.push(val);
  });
  // Add the tasks to run
  spawnOptions.push(task);

  // Return an interface for testing this task
  function returnFunc(runs, done) {
    // Spawn the node this process uses
    var spawnGrunt = spawn(process.argv[0], spawnOptions, {cwd:cwd});
    var out = '';

    if (!grunt.util._.isArray(runs)) {
      runs = [runs];
    }

    // Append a last function to kill spawnGrunt
    runs.push(function() { spawnGrunt.kill('SIGINT'); });

    // After watch starts waiting, run our commands then exit
    spawnGrunt.stdout.on('data', function(data) {
      data = grunt.log.uncolor(String(data));
      out += data;

      // If we should run the next function
      var shouldRun = true;

      // If our trigger has been found
      if (trigger !== false) {
        shouldRun = (grunt.util._.indexOf(data.split("\n"), trigger) !== -1);
      }

      // Run the function
      if (shouldRun) {
        setTimeout(function() {
          var run = runs.shift();
          if (typeof run === 'function') { run(); }
        }, 500);
      }
    });

    // Throw errors for better testing
    spawnGrunt.stderr.on('data', function(data) {
      throw new Error(data);
    });

    // On process exit return what has been outputted
    spawnGrunt.on('exit', function() {
      done(out);
    });
  }
  returnFunc.options = options;
  return returnFunc;
}

exports.watchConfig = {
  oneTarget: function(test) {
    test.expect(2);
    var cwd = path.resolve(fixtures, 'oneTarget');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      var write = 'var test = true;';
      grunt.file.write(path.join(cwd, 'lib', 'one.js'), write);
    }, function(result) {
      verboseLog(result);
      test.ok(result.indexOf('File "lib' + path.sep + 'one.js" changed') !== -1, 'Watch should have fired when oneTarget/lib/one.js has changed.');
      test.ok(result.indexOf('I do absolutely nothing.') !== -1, 'echo task should have fired.');
      test.done();
    });
  },
  multiTargetsTriggerOneNotTwo: function(test) {
    test.expect(2);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      var write = 'var test = true;';
      grunt.file.write(path.join(cwd, 'lib', 'one.js'), write);
    }, function(result) {
      verboseLog(result);
      test.ok(result.indexOf('one has changed') !== -1, 'Only task echo:one should of emit.');
      test.ok(result.indexOf('two has changed') === -1, 'Task echo:two should NOT emit.');
      test.done();
    });
  },
  multiTargetsTriggerBoth: function(test) {
    test.expect(2);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch([function() {
      grunt.file.write(path.join(cwd, 'lib', 'one.js'), 'var test = true;');
    }, function() {
      grunt.file.write(path.join(cwd, 'lib', 'two.js'), 'var test = true;');
    }], function(result) {
      verboseLog(result);
      test.ok(result.indexOf('one has changed') !== -1, 'Task echo:one should of emit.');
      test.ok(result.indexOf('two has changed') !== -1, 'Task echo:two should of emit.');
      test.done();
    });
  },
  spawnOneAtATime: function(test) {
    test.expect(1);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      grunt.file.write(path.join(cwd, 'lib', 'wait.js'), 'var wait = false;');
      setTimeout(function() {
        grunt.file.write(path.join(cwd, 'lib', 'wait.js'), 'var wait = true;');
      }, 500);
    }, function(result) {
      verboseLog(result);
      test.ok(result.indexOf('I waited 2s') !== -1, 'Task should have waited 2s and only spawned once.');
      test.done();
    });
  },
  interrupt: function(test) {
    test.expect(1);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      grunt.file.write(path.join(cwd, 'lib', 'interrupt.js'), 'var interrupt = false;');
      setTimeout(function() {
        grunt.file.write(path.join(cwd, 'lib', 'interrupt.js'), 'var interrupt = true;');
      }, 1000);
    }, function(result) {
      verboseLog(result);
      test.ok(result.indexOf('has been interrupted') !== -1, 'Task should have been interrupted.');
      test.done();
    });
  },
  failingTask: function(test) {
    test.expect(2);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      grunt.file.write(path.join(cwd, 'lib', 'fail.js'), 'var fail = false;');
    }, function(result) {
      verboseLog(result);
      test.ok(result.indexOf('<FATAL>') !== -1, 'Task should have been fatal.');
      test.equal(grunt.util._(result).count('Waiting...'), 2, 'Should have displayed "Wating..." twice');
      test.done();
    });
  }
};
<commit_msg>Fix failing test. Just look for fatal.<commit_after>'use strict';

var grunt = require('grunt');
var path = require('path');
grunt.util = grunt.util || grunt.utils;

// Node v0.6 compat
path.sep = path.sep || path.normalize('/');

// In case the grunt being used to test is different than the grunt being
// tested, initialize the task and config subsystems.
if (grunt.task.searchDirs.length === 0) {
  grunt.task.init([]);
  grunt.config.init({});
}

// Where our fixtures are
var fixtures = path.join(__dirname, '..', 'fixtures');

// If verbose flag set, display output
var verboseLog = function() {};
if (grunt.util._.indexOf(process.argv, '-v') !== -1) {
  verboseLog = function() { console.log.apply(null, arguments); };
}

// helper for creating assertTasks for testing tasks in child processes
function assertTask(task, options) {
  var spawn = require('child_process').spawn;
  task = task || 'default';
  options = options || {};

  // get next/kill process trigger
  var trigger = options.trigger || 'Waiting...';
  delete options.trigger;

  // CWD to spawn
  var cwd = options.cwd || process.cwd();
  delete options.cwd;

  // Use grunt this process uses
  var spawnOptions = [process.argv[1]];
  // Turn options into spawn options
  grunt.util._.each(options, function(val, key) {
    spawnOptions.push('--' + key);
    spawnOptions.push(val);
  });
  // Add the tasks to run
  spawnOptions.push(task);

  // Return an interface for testing this task
  function returnFunc(runs, done) {
    // Spawn the node this process uses
    var spawnGrunt = spawn(process.argv[0], spawnOptions, {cwd:cwd});
    var out = '';

    if (!grunt.util._.isArray(runs)) {
      runs = [runs];
    }

    // Append a last function to kill spawnGrunt
    runs.push(function() { spawnGrunt.kill('SIGINT'); });

    // After watch starts waiting, run our commands then exit
    spawnGrunt.stdout.on('data', function(data) {
      data = grunt.log.uncolor(String(data));
      out += data;

      // If we should run the next function
      var shouldRun = true;

      // If our trigger has been found
      if (trigger !== false) {
        shouldRun = (grunt.util._.indexOf(data.split("\n"), trigger) !== -1);
      }

      // Run the function
      if (shouldRun) {
        setTimeout(function() {
          var run = runs.shift();
          if (typeof run === 'function') { run(); }
        }, 500);
      }
    });

    // Throw errors for better testing
    spawnGrunt.stderr.on('data', function(data) {
      throw new Error(data);
    });

    // On process exit return what has been outputted
    spawnGrunt.on('exit', function() {
      done(out);
    });
  }
  returnFunc.options = options;
  return returnFunc;
}

exports.watchConfig = {
  oneTarget: function(test) {
    test.expect(2);
    var cwd = path.resolve(fixtures, 'oneTarget');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      var write = 'var test = true;';
      grunt.file.write(path.join(cwd, 'lib', 'one.js'), write);
    }, function(result) {
      verboseLog(result);
      test.ok(result.indexOf('File "lib' + path.sep + 'one.js" changed') !== -1, 'Watch should have fired when oneTarget/lib/one.js has changed.');
      test.ok(result.indexOf('I do absolutely nothing.') !== -1, 'echo task should have fired.');
      test.done();
    });
  },
  multiTargetsTriggerOneNotTwo: function(test) {
    test.expect(2);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      var write = 'var test = true;';
      grunt.file.write(path.join(cwd, 'lib', 'one.js'), write);
    }, function(result) {
      verboseLog(result);
      test.ok(result.indexOf('one has changed') !== -1, 'Only task echo:one should of emit.');
      test.ok(result.indexOf('two has changed') === -1, 'Task echo:two should NOT emit.');
      test.done();
    });
  },
  multiTargetsTriggerBoth: function(test) {
    test.expect(2);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch([function() {
      grunt.file.write(path.join(cwd, 'lib', 'one.js'), 'var test = true;');
    }, function() {
      grunt.file.write(path.join(cwd, 'lib', 'two.js'), 'var test = true;');
    }], function(result) {
      verboseLog(result);
      test.ok(result.indexOf('one has changed') !== -1, 'Task echo:one should of emit.');
      test.ok(result.indexOf('two has changed') !== -1, 'Task echo:two should of emit.');
      test.done();
    });
  },
  spawnOneAtATime: function(test) {
    test.expect(1);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      grunt.file.write(path.join(cwd, 'lib', 'wait.js'), 'var wait = false;');
      setTimeout(function() {
        grunt.file.write(path.join(cwd, 'lib', 'wait.js'), 'var wait = true;');
      }, 500);
    }, function(result) {
      verboseLog(result);
      test.ok(result.indexOf('I waited 2s') !== -1, 'Task should have waited 2s and only spawned once.');
      test.done();
    });
  },
  interrupt: function(test) {
    test.expect(1);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      grunt.file.write(path.join(cwd, 'lib', 'interrupt.js'), 'var interrupt = false;');
      setTimeout(function() {
        grunt.file.write(path.join(cwd, 'lib', 'interrupt.js'), 'var interrupt = true;');
      }, 1000);
    }, function(result) {
      verboseLog(result);
      test.ok(result.indexOf('has been interrupted') !== -1, 'Task should have been interrupted.');
      test.done();
    });
  },
  failingTask: function(test) {
    test.expect(2);
    var cwd = path.resolve(fixtures, 'multiTargets');
    var assertWatch = assertTask('watch', {cwd:cwd});
    assertWatch(function() {
      grunt.file.write(path.join(cwd, 'lib', 'fail.js'), 'var fail = false;');
    }, function(result) {
      verboseLog(result);
      test.ok(result.toLowerCase().indexOf('fatal') !== -1, 'Task should have been fatal.');
      test.equal(grunt.util._(result).count('Waiting...'), 2, 'Should have displayed "Wating..." twice');
      test.done();
    });
  }
};
<|endoftext|>


<commit_before>var Builder = require('../index');
var fs = require('fs');

suite('Test builder.loadConfig', function() {

  test('builder.loadConfig works', function(done) {

    var configFile = 'test/output/builderConfig.js';
    var builder = new Builder();
    fs.writeFileSync(configFile, 'System.config({map: {m: "./m.js"}});');
    builder.loadConfig(configFile).then(function() {

      assert.equal(builder.loader.map['m'], './m.js', 'loader map was loaded from config');

    }).then(done, done);

  });

  test('builder.loadConfig does not affect other builders', function(done) {

    var configFile1 = 'test/output/builder1Config.js';
    var configFile2 = 'test/output/builder2Config.js';
    fs.writeFileSync(configFile1, 'System.config({baseURL: "base1", map: {m1: "./m1.js"}, packages: {p1: {main: "index1.js"}}});');
    fs.writeFileSync(configFile2, 'System.config({baseURL: "base2", map: {m2: "./m2.js"}, packages: {p2: {main: "index2.js"}}});');

    var builder1 = new Builder();
    var builder2 = new Builder();

    var p1 = builder1.loadConfig(configFile1);
    var p2 = builder2.loadConfig(configFile2);

    Promise.all([p1, p2]).then(function() {

      assert.match(builder1.loader.baseURL, /base1\/$/, 'builder1 baseURL');
      assert.match(builder2.loader.baseURL, /base2\/$/, 'builder2 baseURL');

      assert.equal(builder1.loader.map['m1'], './m1.js', 'builder1.loader map was loaded from config');
      assert.equal(builder1.loader.map['m2'], undefined, 'map for builder1.loader only');
      assert.equal(builder2.loader.map['m2'], './m2.js', 'builder2.loader map was loaded from config');
      assert.equal(builder2.loader.map['m1'], undefined, 'map for builder2.loader only');

      builder1.loader.normalize('p1').then(function(p1) {
        assert.match(p1, /base1\/p1\/index1\.js$/, 'builder1 package p1');

        assert.equal(builder1.loader.packages['p2'], undefined, 'builder1 package p2');
        assert.equal(builder2.loader.packages['p1'], undefined, 'builder2 package p1');
        builder2.loader.normalize('p2').then(function(p2) {
          assert.match(p2, /base2\/p2\/index2\.js$/, 'builder2 package p2');
        }).then(done, done);
      });
    });
  });

  test('builder.loadConfig does not affect global variables', function(done) {

    global._tmp_1 = '1';

    var configFile = 'test/output/builderConfig.js';
    var builder = new Builder();
    fs.writeFileSync(configFile, '_tmp_1=2; _tmp_2=3; global._tmp_1=4;');
    builder.loadConfig(configFile).then(function() {

      assert.equal(global._tmp_1, '1', 'previously defined global variable is not affected');
      assert.equal(global._tmp_2, undefined, 'new global variables are not defined');

      delete global._tmp_1;

    }).then(done, done);

  });

  test('builder.loadConfig makes require available to config code',  function(done) {
    global._tmp_channel = {};
    var configFile = 'test/output/builderConfig.js';
    var builder = new Builder();
    fs.writeFileSync(configFile, 'global._tmp_channel.result = typeof require;');
    builder.loadConfig(configFile).then(function() {

      assert.equal(global._tmp_channel.result, 'function', 'typeof require === \'function\'');

      delete global._tmp_channel;

    }).then(done, done);

  });

});
<commit_msg>change loadConfig test for require: just call require, don't check for it<commit_after>var Builder = require('../index');
var fs = require('fs');

suite('Test builder.loadConfig', function() {

  test('builder.loadConfig works', function(done) {

    var configFile = 'test/output/builderConfig.js';
    var builder = new Builder();
    fs.writeFileSync(configFile, 'System.config({map: {m: "./m.js"}});');
    builder.loadConfig(configFile).then(function() {

      assert.equal(builder.loader.map['m'], './m.js', 'loader map was loaded from config');

    }).then(done, done);

  });

  test('builder.loadConfig does not affect other builders', function(done) {

    var configFile1 = 'test/output/builder1Config.js';
    var configFile2 = 'test/output/builder2Config.js';
    fs.writeFileSync(configFile1, 'System.config({baseURL: "base1", map: {m1: "./m1.js"}, packages: {p1: {main: "index1.js"}}});');
    fs.writeFileSync(configFile2, 'System.config({baseURL: "base2", map: {m2: "./m2.js"}, packages: {p2: {main: "index2.js"}}});');

    var builder1 = new Builder();
    var builder2 = new Builder();

    var p1 = builder1.loadConfig(configFile1);
    var p2 = builder2.loadConfig(configFile2);

    Promise.all([p1, p2]).then(function() {

      assert.match(builder1.loader.baseURL, /base1\/$/, 'builder1 baseURL');
      assert.match(builder2.loader.baseURL, /base2\/$/, 'builder2 baseURL');

      assert.equal(builder1.loader.map['m1'], './m1.js', 'builder1.loader map was loaded from config');
      assert.equal(builder1.loader.map['m2'], undefined, 'map for builder1.loader only');
      assert.equal(builder2.loader.map['m2'], './m2.js', 'builder2.loader map was loaded from config');
      assert.equal(builder2.loader.map['m1'], undefined, 'map for builder2.loader only');

      builder1.loader.normalize('p1').then(function(p1) {
        assert.match(p1, /base1\/p1\/index1\.js$/, 'builder1 package p1');

        assert.equal(builder1.loader.packages['p2'], undefined, 'builder1 package p2');
        assert.equal(builder2.loader.packages['p1'], undefined, 'builder2 package p1');
        builder2.loader.normalize('p2').then(function(p2) {
          assert.match(p2, /base2\/p2\/index2\.js$/, 'builder2 package p2');
        }).then(done, done);
      });
    });
  });

  test('builder.loadConfig does not affect global variables', function(done) {

    global._tmp_1 = '1';

    var configFile = 'test/output/builderConfig.js';
    var builder = new Builder();
    fs.writeFileSync(configFile, '_tmp_1=2; _tmp_2=3; global._tmp_1=4;');
    builder.loadConfig(configFile).then(function() {

      assert.equal(global._tmp_1, '1', 'previously defined global variable is not affected');
      assert.equal(global._tmp_2, undefined, 'new global variables are not defined');

      delete global._tmp_1;

    }).then(done, done);

  });

  test('builder.loadConfig makes require available to config code',  function(done) {
    var configFile = 'test/output/builderConfig.js';
    var builder = new Builder();
    fs.writeFileSync(configFile, 'var m = require("module"); System.config({baseURL:"base"});');
    builder.loadConfig(configFile).then(function() {

      assert.match(builder.loader.baseURL, /base\/$/, 'builder baseURL set');

    }).then(done, done);

  });

});
<|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) {
        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json');
        var ioPackage = JSON.parse(fileContentIOPackage);

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

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

        expect(ioPackage.common.version).to.exist;
        expect(npmPackage.version).to.exist;

        if (!expect(ioPackage.common.version).to.be.equal(npmPackage.version)) {
            console.log('ERROR: Version numbers in package.json and io-package.json differ!!');
        }

        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!');
        }

        expect(ioPackage.common.authors).to.exist;
        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length).to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0]).to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors).to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('Testing for set authors field in io-package skipped because template adapter');
        }
        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;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        expect(fileContentReadme.indexOf('## License'), 'The README.md needs to have a section ## License').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## Changelog').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## License').to.be.below(fileContentReadme.indexOf('## License'));
        done();
    });
});
<|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;
        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();
    });
});
<commit_msg>update basic package-file testing<commit_after>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
'use strict';

const expect = require('chai').expect;
const fs     = require('fs');

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

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

        const fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        const 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;

        expect(ioPackage.common.license, 'ERROR: License missing in io-package in common.license').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;
        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.controller && !ioPackage.common.onlyWWW && !ioPackage.common.noConfig) {
            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;
            }
        }

        const licenseFileExists = fs.existsSync(__dirname + '/../LICENSE');
        const 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 constants = require('../constants');
var tools = require('../tools');

var exports = module.exports = parseData;

function parseData(buffer) {
    //console.log('parser')
    //console.log(buffer.toString('hex'));

    var cmdCode = buffer.slice(2,3).toString('hex');
    var msgLen = buffer.slice(3,4).toString('hex');

    if (cmdCode == constants.commands.BCSA.cmd) {
        exports.parsers.BCSA(buffer);
    }

}

exports.parsers = {};

exports.parsers.BCSA = function(buffer) {
    var res = {cmd:'BCSA'};

    res.msgLen = buffer.slice(3,4).toString('hex');

    // msg split
    //  4,6 - HW ver
    res.hardwareVersion = buffer.slice(4,6).toString('hex');
    //console.log('hw version', hwVer); // does anyone really care about this?

    //  6,8 - SW ver
    res.softwareVersion = buffer.slice(6,8).toString('hex');
    //console.log('sw version', swVer); // honestly, who cares?

    //  8, length-9 - WRC name
    //  -9: 7 for field length, 2 for crc
    res.wrcName = buffer.slice(8,buffer.length-9).toString('ascii');
    //console.log('car name', wrcName);

    //  length-9,length - serial
    res.serialNum = buffer.slice(buffer.length-9,buffer.length).toString('ascii');
    //console.log('serial number', serialNum);

    return res;
};

// TESTME
exports.parser.WST = function(buffer) {
    var res = {cmd:'WST'};

    res.msgLen = buffer.slice(3,4);

    // ID - transmitter id
    res.transmitterId = buffer.slice(4,5);

    // CN - number of connected cameras
    res.numberOfCameras = buffer.slice(5,6);

    // PORT - control port - to send PCD messages
    res.controlPort = buffer.slice(6,8);

    return res;
};

// TESTME
exports.parser.AGR = function(buffer) {
    var res = {cmd:'AGR'};

    res.msgLen = buffer.slice(3,4);

    // ID - transmitter id
    res.transmitterId = buffer.slice(4,5);

    // Prio - priority of transmitter
    res.priority = buffer.slice(5,6);

    // Transmitter name (64 bytes)
    res.transmitterName = buffer.slice(6, buffer.length-3).toString('ascii');

    // Control notification: 0 granted, 1 denied requested, 2 access lost, 3 granted to everyone
    res.controlGrant = buffer.slice(buffer.length-3, buffer.length-2);

    return res;
};

// TESTME
exports.parser.PSD = function(buffer) {
    var res = {cmd:'PSD'};

    res.msgLen = buffer.slice(3,4);

    // Batt 1 - battery voltage, integer value in millivolts
    res.battery1 = buffer.slice(4,6);

    // Batt 2 - analogue input voltage, integer value in millivolts .
    res.battery2 = buffer.slice(6,8);

    // IN 1 - state of digital input 1
    res.digitalIn1 = buffer.slice(8,9);

    // IN 2
    res.digitalIn2 = buffer.slice(9,10);

    // IN 3
    res.digitalIn3 = buffer.slice(10,11);

    // IN 4
    res.digitalIn4 = buffer.slice(11,12);

    return res;

};

// TESTME
exports.parser.TLST = function(buffer) {
    var res = {cmd:'TLST'};
    res.msgLen = buffer.slice(3,4);

    // ID - transmitter id
    res.transmitterId = buffer.slice(4,5);

    // Prio - priority of transmitter
    res.priority = buffer.slice(5,6);

    // Transmitter name (64 bytes)
    res.transmitterName = buffer.slice(6, buffer.length-2).toString('ascii');

    return res;
};

exports.parser.TLEND = function(buffer) {
    var res = {cmd:'TLEND'};
    res.msgLen = 0;

    return res;
};

// TESTME
exports.parser.ERR = function(buffer) {
    var res = {cmd:'ERR'};
    res.msgLen = buffer.slice(3,4);

    // command code that produced the error
    res.cmdErr = buffer.slice(4,5);

    // error code
    res.errCode = buffer.slice(5,7);

    return res;
};
<commit_msg>add error data<commit_after>var constants = require('../constants');
var tools = require('../tools');

var exports = module.exports = parseData;

function parseData(buffer) {
    //console.log('parser')
    //console.log(buffer.toString('hex'));

    var cmdCode = buffer.slice(2,3).toString('hex');
    var msgLen = buffer.slice(3,4).toString('hex');

    if (cmdCode == constants.commands.BCSA.cmd) {
        exports.parsers.BCSA(buffer);
    }

}

exports.parsers = {};

exports.parsers.BCSA = function(buffer) {
    var res = {cmd:'BCSA'};

    res.msgLen = buffer.slice(3,4).toString('hex');

    // msg split
    //  4,6 - HW ver
    res.hardwareVersion = buffer.slice(4,6).toString('hex');
    //console.log('hw version', hwVer); // does anyone really care about this?

    //  6,8 - SW ver
    res.softwareVersion = buffer.slice(6,8).toString('hex');
    //console.log('sw version', swVer); // honestly, who cares?

    //  8, length-9 - WRC name
    //  -9: 7 for field length, 2 for crc
    res.wrcName = buffer.slice(8,buffer.length-9).toString('ascii');
    //console.log('car name', wrcName);

    //  length-9,length - serial
    res.serialNum = buffer.slice(buffer.length-9,buffer.length).toString('ascii');
    //console.log('serial number', serialNum);

    return res;
};

// TESTME
exports.parser.WST = function(buffer) {
    var res = {cmd:'WST'};

    res.msgLen = buffer.slice(3,4);

    // ID - transmitter id
    res.transmitterId = buffer.slice(4,5);

    // CN - number of connected cameras
    res.numberOfCameras = buffer.slice(5,6);

    // PORT - control port - to send PCD messages
    res.controlPort = buffer.slice(6,8);

    return res;
};

// TESTME
exports.parser.AGR = function(buffer) {
    var res = {cmd:'AGR'};

    res.msgLen = buffer.slice(3,4);

    // ID - transmitter id
    res.transmitterId = buffer.slice(4,5);

    // Prio - priority of transmitter
    res.priority = buffer.slice(5,6);

    // Transmitter name (64 bytes)
    res.transmitterName = buffer.slice(6, buffer.length-3).toString('ascii');

    // Control notification: 0 granted, 1 denied requested, 2 access lost, 3 granted to everyone
    res.controlGrant = buffer.slice(buffer.length-3, buffer.length-2);

    return res;
};

// TESTME
exports.parser.PSD = function(buffer) {
    var res = {cmd:'PSD'};

    res.msgLen = buffer.slice(3,4);

    // Batt 1 - battery voltage, integer value in millivolts
    res.battery1 = buffer.slice(4,6);

    // Batt 2 - analogue input voltage, integer value in millivolts .
    res.battery2 = buffer.slice(6,8);

    // IN 1 - state of digital input 1
    res.digitalIn1 = buffer.slice(8,9);

    // IN 2
    res.digitalIn2 = buffer.slice(9,10);

    // IN 3
    res.digitalIn3 = buffer.slice(10,11);

    // IN 4
    res.digitalIn4 = buffer.slice(11,12);

    return res;

};

// TESTME
exports.parser.TLST = function(buffer) {
    var res = {cmd:'TLST'};
    res.msgLen = buffer.slice(3,4);

    // ID - transmitter id
    res.transmitterId = buffer.slice(4,5);

    // Prio - priority of transmitter
    res.priority = buffer.slice(5,6);

    // Transmitter name (64 bytes)
    res.transmitterName = buffer.slice(6, buffer.length-2).toString('ascii');

    return res;
};

exports.parser.TLEND = function(buffer) {
    var res = {cmd:'TLEND'};
    res.msgLen = 0;

    return res;
};

// TESTME
exports.parser.ERR = function(buffer) {
    var res = {cmd:'ERR'};
    res.msgLen = buffer.slice(3,4);

    // command code that produced the error
    res.cmdErr = buffer.slice(4,5);

    // error code
    res.errCode = buffer.slice(5,7);

    res.errMsg = (function(i){
        var err = [
            {errType:'MSG_ERR_NONE',errMessage: 'No error'},
            {errType:'MSG_ERR_FORMAT',errMessage: 'Message format error (i.e. invalid value or invalid length)'},
            {errType:'MSG_ERR_DENIED',errMessage: 'Permission denied!'},
            {errType:'MSG_ERR_SYS',errMessage: 'General system error in WRC mechanism'},
            {errType:'MSG_ERR_SAVE',errMessage: 'Unable to save actual configuration'},
            {errType:'MSG_ERR_UNAUTH',errMessage: 'Unauthorized connection'},
            {errType:'MSG_ERR_BUSY',errMessage: 'IP address is busy'}];
        return err[i];
    })(res.errCode);

    // #define MSG_ERR_NONE        0x0000      /* No error */
    // #define MSG_ERR_FORMAT      0x0001      /* Message fomat error (i.e. invalid value or invalid length) */
    // #define MSG_ERR_DENIED      0x0002      /* Permission denied! */
    // #define MSG_ERR_SYS         0x0003      /* General system error in WRC mechanism */
    // #define MSG_ERR_SAVE        0x0004      /* Unable to save actual configuration */
    // #define MSG_ERR_UNAUTH      0x0005      /* Unauthorized connection */
    // #define MSG_ERR_BUSY        0x0006      /* IP address is busy */

    return res;
};
<|endoftext|>


<commit_before>'use strict';

(function() {

  var addBrowserContainer = function(Y) {
    var docBody = Y.one(document.body);
    Y.Node.create('
' +
        '
').appendTo(docBody);
  };

  describe('browser fullscreen view', function() {
    var browser, FullScreen, view, views, Y;

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'juju-views',
          'juju-browser',
          'subapp-browser-fullscreen', function(Y) {
            browser = Y.namespace('juju.browser');
            views = Y.namespace('juju.browser.views');
            FullScreen = views.FullScreen;
            done();
          });
    });

    beforeEach(function() {
      addBrowserContainer(Y);
      // Mock out a dummy location for the Store used in view instances.
      window.juju_config = {
        charmworldURL: 'http://localhost'
      };

    });

    afterEach(function() {
      view.destroy();
      Y.one('#subapp-browser').remove(true);
      delete window.juju_config;
    });

    it('knows that it is fullscreen', function() {
      view = new FullScreen();
      view.isFullscreen().should.equal(true);
    });

    // Ensure the search results are rendered inside the container.
    it('must correctly render the initial browser ui', function() {
      var container = Y.one('#subapp-browser');

      view = new FullScreen();
      view.render(container);

      // And the hide button is rendered to the container node.
      assert.isTrue(Y.Lang.isObject(container.one('#bws-fullscreen')));
      // Also verify that the search widget has rendered into the view code.
      assert.isTrue(Y.Lang.isObject(container.one('input')));
    });

    it('reroutes to minimized when toggled', function(done) {
      var container = Y.one('#subapp-browser');
      view = new FullScreen();
      view.on('viewNavigate', function(ev) {
        assert(ev.change.viewmode === 'minimized');
        done();
      });
      view.render(container);
      container.one('.bws-icon').simulate('click');
    });

  });
})();

(function() {
  var addBrowserContainer = function(Y) {
    var docBody = Y.one(document.body);
    Y.Node.create('
' +
        '
').appendTo(docBody);
  };

  describe('browser sidebar view', function() {
    var Y, browser, models, view, views, Sidebar;

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'juju-browser',
          'juju-models',
          'juju-views',
          'node-event-simulate',
          'subapp-browser-sidebar',
          function(Y) {
            browser = Y.namespace('juju.browser');
            views = Y.namespace('juju.browser.views');
            Sidebar = views.Sidebar;
            done();
          });
    });

    beforeEach(function() {
      addBrowserContainer(Y);
      // Mock out a dummy location for the Store used in view instances.
      window.juju_config = {
        charmworldURL: 'http://localhost'
      };
    });

    afterEach(function() {
      view.destroy();
      Y.one('#subapp-browser').remove(true);
      delete window.juju_config;
    });

    it('knows that it is not fullscreen', function() {
      view = new Sidebar();
      view.isFullscreen().should.equal(false);
    });

    it('reroutes to minimized when toggled', function(done) {
      var container = Y.one('#subapp-browser');
      view = new Sidebar();
      view.on('viewNavigate', function(ev) {
        assert(ev.change.viewmode === 'minimized');
        done();
      });
      view.render(container);
      container.one('.bws-icon').simulate('click');
    });

    it('must correctly render the initial browser ui', function() {
      var container = Y.one('#subapp-browser');
      view = new Sidebar({
        store: new Y.juju.Charmworld0({
          apiHost: 'http://localhost'
        })
      });

      // mock out the data source on the view so that it won't actually make a
      // request.
      var emptyData = {
        responseText: Y.JSON.stringify({
          result: {
            'new': [],
            slider: []
          }
        })
      };

      // Override the store to not call the dummy localhost address.
      view.get('store').set(
          'datasource',
          new Y.DataSource.Local({source: emptyData}));
      view.render(container);

      // And the hide button is rendered to the container node.
      assert.isTrue(Y.Lang.isObject(container.one('#bws-sidebar')));
      // Also verify that the search widget has rendered into the view code.
      assert.isTrue(Y.Lang.isObject(container.one('input')));
    });

  });
})();

(function() {
  describe('browser app', function() {
    var Y, app, browser;

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'app-subapp-extension',
          'juju-views',
          'juju-browser',
          'subapp-browser', function(Y) {
            browser = Y.namespace('juju.subapps');
            done();
          });
    });

    afterEach(function() {
      if (app) {
        app.destroy();
      }
    });

    it('verify that route callables exist', function() {
      app = new browser.Browser();
      Y.each(app.get('routes'), function(route) {
        assert.isTrue(typeof app[route.callback] === 'function');
      });
    });

  });

  describe('browser subapp display tree', function() {
    var Y, browser, hits, ns, resetHits;

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'app-subapp-extension',
          'juju-views',
          'juju-browser',
          'subapp-browser', function(Y) {
            browser = Y.namespace('juju.subapps');

            resetHits = function() {
              hits = {
                fullscreen: false,
                minimized: false,
                sidebar: false,
                renderCharmDetails: false,
                renderEditorial: false,
                renderSearchResults: false
              };
            };
            done();
          });
    });

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'juju-views',
          'juju-browser',
          'subapp-browser', function(Y) {
            ns = Y.namespace('juju.subapps');
            done();
          });
    });

    beforeEach(function() {
      var docBody = Y.one(document.body);
      Y.Node.create('

' +
          '

').appendTo(docBody);

      // Track which render functions are hit.
      resetHits();

      // Mock out a dummy location for the Store used in view instances.
      window.juju_config = {
        charmworldURL: 'http://localhost'
      };

      browser = new ns.Browser();
      // Block out each render target so we only track it was hit.
      browser.renderCharmDetails = function() {
        hits.renderCharmDetails = true;
      };
      browser.renderEditorial = function() {
        hits.renderEditorial = true;
      };
      browser.renderSearchResults = function() {
        hits.renderSearchResults = true;
      };
      browser.minimized = function() {
        hits.minimized = true;
      };
      // showView needs to be hacked because it does the rendering of
      // fullscreen/sidebar.
      browser.showView = function(view) {
        hits[view] = true;
      };
    });

    afterEach(function() {
      browser.destroy();
      Y.one('#subapp-browser').remove(true);
    });

    it('/ dispatches correctly', function() {
      var req = {
        path: '/'
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderEditorial: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar dispatches correctly', function() {
      var req = {
        path: '/sidebar/',
        params: {
          viewmode: 'sidebar'
        }
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderEditorial: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/charmid dispatches correctly', function() {
      var req = {
        path: '/precise/apache2-2',
        params: {
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderEditorial: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar/charmid dispatches correctly', function() {
      var req = {
        path: '/sidebar/precise/apache2-2',
        params: {
          viewmode: 'sidebar',
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderEditorial: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar/search/charmid dispatches correctly', function() {
      var req = {
        path: '/sidebar/search/precise/apache2-2',
        params: {
          viewmode: 'sidebar',
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderSearchResults: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen dispatches correctly', function() {
      var req = {
        path: '/fullscreen/',
        params: {
          viewmode: 'fullscreen'
        }
      };
      var expected = Y.merge(hits, {
        fullscreen: true,
        renderEditorial: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen/charmid dispatches correctly', function() {
      var req = {
        path: '/fullscreen/precise/apache2-2',
        params: {
          viewmode: 'fullscreen',
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        fullscreen: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen/search/charmid dispatches correctly', function() {
      var req = {
        path: '/fullscreen/search/precise/apache2-2',
        params: {
          viewmode: 'fullscreen',
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        fullscreen: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar to /sidebar/charmid dispatches correctly', function() {
      var req = {
        path: '/sidebar/',
        params: {
          viewmode: 'sidebar'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Now route through to the charmid from here and we should not hit the
      // editorial content again.
      resetHits();
      req = {
        path: '/sidebar/precise/apache2-2',
        params: {
          viewmode: 'sidebar',
          id: 'precise/apache2-2'
        }
      };

      var expected = Y.merge(hits, {
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar/charmid to /sidebar dispatchse correctly', function() {
      var req = {
        path: '/sidebar/precise/apache2-2',
        params: {
          viewmode: 'sidebar',
          id: 'precise/apache2-2'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();
      req = {
        path: '/sidebar/',
        params: {
          viewmode: 'sidebar'
        }
      };

      var expected = Y.merge(hits, {});
      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen to /fullscreen/charmid dispatches correctly', function() {
      var req = {
        path: '/fullscreen/',
        params: {
          viewmode: 'fullscreen'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Now route through to the charmid from here and we should not hit the
      // editorial content again.
      resetHits();
      req = {
        path: '/fullscreen/precise/apache2-2',
        params: {
          viewmode: 'fullscreen',
          id: 'precise/apache2-2'
        }
      };

      var expected = Y.merge(hits, {
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen/details to /fullscreen renders editorial', function() {
      var req = {
        path: '/fullscreen/precise/apache2-2',
        params: {
          viewmode: 'fullscreen',
          id: 'precise/apache2-2'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();
      req = {
        path: '/fullscreen/',
        params: {
          viewmode: 'fullscreen'
        }
      };

      var expected = Y.merge(hits, {
        renderEditorial: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar to /fullscreen dispatches correctly', function() {
      var req = {
        path: '/sidebar',
        params: {
          viewmode: 'sidebar'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();
      req = {
        path: '/fullscreen/',
        params: {
          viewmode: 'fullscreen'
        }
      };

      var expected = Y.merge(hits, {
        fullscreen: true,
        renderEditorial: true
      });
      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('changing the query string dispatches correctly', function() {
      var req = {
        path: '/fullscreen/search/',
        params: {
          viewmode: 'fullscreen'
        },
        query: {
          text: 'test'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();
      req.query.text = 'test2';

      var expected = Y.merge(hits, {
        renderSearchResults: true
      });
      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('no change to query string does not redraw', function() {
      var req = {
        path: '/fullscreen/search/',
        params: {
          viewmode: 'fullscreen'
        },
        query: {
          text: 'test'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();

      var expected = Y.merge(hits);
      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('searches without a query string function', function() {
      var req = {
        path: '/fullscreen/search/',
        params: {
          viewmode: 'fullscreen'
        }
      };

      var expected = Y.merge(hits, {
        fullscreen: true,
        renderSearchResults: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/minimized dispatches correctly', function() {
      var req = {
        path: '/minimized',
        params: {
          viewmode: 'minimized'
        }
      };

      var expected = Y.merge(hits, {
        minimized: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('when hidden the browser avoids routing', function() {
      browser.hidden = true;

      var req = {
        path: '/minimized',
        params: {
          viewmode: 'minimized'
        }
      };
      var expected = Y.merge(hits);

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);

      // And both nodes are hidden.
      var minNode = Y.one('#subapp-browser-min');
      var browserNode = Y.one('#subapp-browser');

      minNode.getComputedStyle('display').should.eql('none');
      browserNode.getComputedStyle('display').should.eql('none');
    });

  });
})();

<commit_msg>Garden<commit_after>'use strict';

(function() {

  var addBrowserContainer = function(Y) {
    var docBody = Y.one(document.body);
    Y.Node.create('
' +
        '
').appendTo(docBody);
  };

  describe('browser fullscreen view', function() {
    var browser, FullScreen, view, views, Y;

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'juju-views',
          'juju-browser',
          'subapp-browser-fullscreen', function(Y) {
            browser = Y.namespace('juju.browser');
            views = Y.namespace('juju.browser.views');
            FullScreen = views.FullScreen;
            done();
          });
    });

    beforeEach(function() {
      addBrowserContainer(Y);
      // Mock out a dummy location for the Store used in view instances.
      window.juju_config = {
        charmworldURL: 'http://localhost'
      };

    });

    afterEach(function() {
      view.destroy();
      Y.one('#subapp-browser').remove(true);
      delete window.juju_config;
    });

    it('knows that it is fullscreen', function() {
      view = new FullScreen();
      view.isFullscreen().should.equal(true);
    });

    // Ensure the search results are rendered inside the container.
    it('must correctly render the initial browser ui', function() {
      var container = Y.one('#subapp-browser');

      view = new FullScreen();
      view.render(container);

      // And the hide button is rendered to the container node.
      assert.isTrue(Y.Lang.isObject(container.one('#bws-fullscreen')));
      // Also verify that the search widget has rendered into the view code.
      assert.isTrue(Y.Lang.isObject(container.one('input')));
    });

    it('reroutes to minimized when toggled', function(done) {
      var container = Y.one('#subapp-browser');
      view = new FullScreen();
      view.on('viewNavigate', function(ev) {
        assert(ev.change.viewmode === 'minimized');
        done();
      });
      view.render(container);
      container.one('.bws-icon').simulate('click');
    });

  });
})();

(function() {
  var addBrowserContainer = function(Y) {
    var docBody = Y.one(document.body);
    Y.Node.create('
' +
        '
').appendTo(docBody);
  };

  describe('browser sidebar view', function() {
    var Y, browser, view, views, Sidebar;

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'juju-browser',
          'juju-models',
          'juju-views',
          'node-event-simulate',
          'subapp-browser-sidebar',
          function(Y) {
            browser = Y.namespace('juju.browser');
            views = Y.namespace('juju.browser.views');
            Sidebar = views.Sidebar;
            done();
          });
    });

    beforeEach(function() {
      addBrowserContainer(Y);
      // Mock out a dummy location for the Store used in view instances.
      window.juju_config = {
        charmworldURL: 'http://localhost'
      };
    });

    afterEach(function() {
      view.destroy();
      Y.one('#subapp-browser').remove(true);
      delete window.juju_config;
    });

    it('knows that it is not fullscreen', function() {
      view = new Sidebar();
      view.isFullscreen().should.equal(false);
    });

    it('reroutes to minimized when toggled', function(done) {
      var container = Y.one('#subapp-browser');
      view = new Sidebar();
      view.on('viewNavigate', function(ev) {
        assert(ev.change.viewmode === 'minimized');
        done();
      });
      view.render(container);
      container.one('.bws-icon').simulate('click');
    });

    it('must correctly render the initial browser ui', function() {
      var container = Y.one('#subapp-browser');
      view = new Sidebar({
        store: new Y.juju.Charmworld0({
          apiHost: 'http://localhost'
        })
      });

      // mock out the data source on the view so that it won't actually make a
      // request.
      var emptyData = {
        responseText: Y.JSON.stringify({
          result: {
            'new': [],
            slider: []
          }
        })
      };

      // Override the store to not call the dummy localhost address.
      view.get('store').set(
          'datasource',
          new Y.DataSource.Local({source: emptyData}));
      view.render(container);

      // And the hide button is rendered to the container node.
      assert.isTrue(Y.Lang.isObject(container.one('#bws-sidebar')));
      // Also verify that the search widget has rendered into the view code.
      assert.isTrue(Y.Lang.isObject(container.one('input')));
    });

  });
})();

(function() {
  describe('browser app', function() {
    var Y, app, browser;

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'app-subapp-extension',
          'juju-views',
          'juju-browser',
          'subapp-browser', function(Y) {
            browser = Y.namespace('juju.subapps');
            done();
          });
    });

    afterEach(function() {
      if (app) {
        app.destroy();
      }
    });

    it('verify that route callables exist', function() {
      app = new browser.Browser();
      Y.each(app.get('routes'), function(route) {
        assert.isTrue(typeof app[route.callback] === 'function');
      });
    });

  });

  describe('browser subapp display tree', function() {
    var Y, browser, hits, ns, resetHits;

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'app-subapp-extension',
          'juju-views',
          'juju-browser',
          'subapp-browser', function(Y) {
            browser = Y.namespace('juju.subapps');

            resetHits = function() {
              hits = {
                fullscreen: false,
                minimized: false,
                sidebar: false,
                renderCharmDetails: false,
                renderEditorial: false,
                renderSearchResults: false
              };
            };
            done();
          });
    });

    before(function(done) {
      Y = YUI(GlobalConfig).use(
          'juju-views',
          'juju-browser',
          'subapp-browser', function(Y) {
            ns = Y.namespace('juju.subapps');
            done();
          });
    });

    beforeEach(function() {
      var docBody = Y.one(document.body);
      Y.Node.create('

' +
          '

').appendTo(docBody);

      // Track which render functions are hit.
      resetHits();

      // Mock out a dummy location for the Store used in view instances.
      window.juju_config = {
        charmworldURL: 'http://localhost'
      };

      browser = new ns.Browser();
      // Block out each render target so we only track it was hit.
      browser.renderCharmDetails = function() {
        hits.renderCharmDetails = true;
      };
      browser.renderEditorial = function() {
        hits.renderEditorial = true;
      };
      browser.renderSearchResults = function() {
        hits.renderSearchResults = true;
      };
      browser.minimized = function() {
        hits.minimized = true;
      };
      // showView needs to be hacked because it does the rendering of
      // fullscreen/sidebar.
      browser.showView = function(view) {
        hits[view] = true;
      };
    });

    afterEach(function() {
      browser.destroy();
      Y.one('#subapp-browser').remove(true);
    });

    it('/ dispatches correctly', function() {
      var req = {
        path: '/'
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderEditorial: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar dispatches correctly', function() {
      var req = {
        path: '/sidebar/',
        params: {
          viewmode: 'sidebar'
        }
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderEditorial: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/charmid dispatches correctly', function() {
      var req = {
        path: '/precise/apache2-2',
        params: {
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderEditorial: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar/charmid dispatches correctly', function() {
      var req = {
        path: '/sidebar/precise/apache2-2',
        params: {
          viewmode: 'sidebar',
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderEditorial: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar/search/charmid dispatches correctly', function() {
      var req = {
        path: '/sidebar/search/precise/apache2-2',
        params: {
          viewmode: 'sidebar',
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        sidebar: true,
        renderSearchResults: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen dispatches correctly', function() {
      var req = {
        path: '/fullscreen/',
        params: {
          viewmode: 'fullscreen'
        }
      };
      var expected = Y.merge(hits, {
        fullscreen: true,
        renderEditorial: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen/charmid dispatches correctly', function() {
      var req = {
        path: '/fullscreen/precise/apache2-2',
        params: {
          viewmode: 'fullscreen',
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        fullscreen: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen/search/charmid dispatches correctly', function() {
      var req = {
        path: '/fullscreen/search/precise/apache2-2',
        params: {
          viewmode: 'fullscreen',
          id: 'precise/apache2-2'
        }
      };
      var expected = Y.merge(hits, {
        fullscreen: true,
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar to /sidebar/charmid dispatches correctly', function() {
      var req = {
        path: '/sidebar/',
        params: {
          viewmode: 'sidebar'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Now route through to the charmid from here and we should not hit the
      // editorial content again.
      resetHits();
      req = {
        path: '/sidebar/precise/apache2-2',
        params: {
          viewmode: 'sidebar',
          id: 'precise/apache2-2'
        }
      };

      var expected = Y.merge(hits, {
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar/charmid to /sidebar dispatchse correctly', function() {
      var req = {
        path: '/sidebar/precise/apache2-2',
        params: {
          viewmode: 'sidebar',
          id: 'precise/apache2-2'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();
      req = {
        path: '/sidebar/',
        params: {
          viewmode: 'sidebar'
        }
      };

      var expected = Y.merge(hits, {});
      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen to /fullscreen/charmid dispatches correctly', function() {
      var req = {
        path: '/fullscreen/',
        params: {
          viewmode: 'fullscreen'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Now route through to the charmid from here and we should not hit the
      // editorial content again.
      resetHits();
      req = {
        path: '/fullscreen/precise/apache2-2',
        params: {
          viewmode: 'fullscreen',
          id: 'precise/apache2-2'
        }
      };

      var expected = Y.merge(hits, {
        renderCharmDetails: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/fullscreen/details to /fullscreen renders editorial', function() {
      var req = {
        path: '/fullscreen/precise/apache2-2',
        params: {
          viewmode: 'fullscreen',
          id: 'precise/apache2-2'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();
      req = {
        path: '/fullscreen/',
        params: {
          viewmode: 'fullscreen'
        }
      };

      var expected = Y.merge(hits, {
        renderEditorial: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/sidebar to /fullscreen dispatches correctly', function() {
      var req = {
        path: '/sidebar',
        params: {
          viewmode: 'sidebar'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();
      req = {
        path: '/fullscreen/',
        params: {
          viewmode: 'fullscreen'
        }
      };

      var expected = Y.merge(hits, {
        fullscreen: true,
        renderEditorial: true
      });
      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('changing the query string dispatches correctly', function() {
      var req = {
        path: '/fullscreen/search/',
        params: {
          viewmode: 'fullscreen'
        },
        query: {
          text: 'test'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();
      req.query.text = 'test2';

      var expected = Y.merge(hits, {
        renderSearchResults: true
      });
      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('no change to query string does not redraw', function() {
      var req = {
        path: '/fullscreen/search/',
        params: {
          viewmode: 'fullscreen'
        },
        query: {
          text: 'test'
        }
      };
      browser.routeView(req, undefined, function() {});

      // Reset the hits and we should not redraw anything to update the view.
      resetHits();

      var expected = Y.merge(hits);
      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('searches without a query string function', function() {
      var req = {
        path: '/fullscreen/search/',
        params: {
          viewmode: 'fullscreen'
        }
      };

      var expected = Y.merge(hits, {
        fullscreen: true,
        renderSearchResults: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('/minimized dispatches correctly', function() {
      var req = {
        path: '/minimized',
        params: {
          viewmode: 'minimized'
        }
      };

      var expected = Y.merge(hits, {
        minimized: true
      });

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);
    });

    it('when hidden the browser avoids routing', function() {
      browser.hidden = true;

      var req = {
        path: '/minimized',
        params: {
          viewmode: 'minimized'
        }
      };
      var expected = Y.merge(hits);

      browser.routeView(req, undefined, function() {});
      assert.deepEqual(hits, expected);

      // And both nodes are hidden.
      var minNode = Y.one('#subapp-browser-min');
      var browserNode = Y.one('#subapp-browser');

      minNode.getComputedStyle('display').should.eql('none');
      browserNode.getComputedStyle('display').should.eql('none');
    });

  });
})();

<|endoftext|>


<commit_before>(function () {
    'use strict';

    var app = angular.module('SharedDirectives');

    /**
     * @ngdoc directive
     * @name SharedDirectives.directive:ok-toggle-color
     * @restrict A
     * @requires SharedDirectives.directive:ok-collapse
     *
     * @description
     * `ok-toggle-color`
     *
     *  Added to an element that has an ok-collapse attribute attached to it. Requires the same attributes as ok-collapse.
     *  Toggles primary to warning color and minus to plus classes (font awesome).
     * @usage
     * <button ok-collapse ok-toggle-color linked-to="uniqueId" all-linked-nodes="['uniqueIdOne', 'uniqueIdTwo']">
     *
     *</button>
     *

     *

     */

    function okToggleColor() {
        return {
            restrict: 'A',
            link: linkFunc
        };

        function linkFunc(scope, iElement, iAttrs) {
            var collapseScope = iElement.isolateScope();

            function replaceClass(oldClass, newClass, element) {
                element.addClass(newClass);
                element.removeClass(oldClass);
            }

            function resetAllButtons(iconElements, buttonElement) {
                var i;
                for (i = 0; i < iconElements.length; i++) {
                    var currentElement = angular.element(iconElements[i]);
                    if (currentElement.hasClass('fa') && !currentElement.hasClass('fa-pencil')) {
                        replaceClass('fa-minus', 'fa-plus', currentElement);
                        currentElement.parent().removeClass('md-warn');
                        currentElement.parent().removeClass('md-primary');
                    }
                }
            }

            function disableChildren(collapseScope, thisElement) {
                var allNodes = collapseScope.allLinkedNodes,
                    i = allNodes.indexOf(collapseScope.linkedTo);
                for (i; i < allNodes.length; i++) {
                    var node = angular.element(document.getElementById(allNodes[i]));

                    node.children().removeClass('active');

                    resetAllButtons(node.find('a').find('i'), node.find('a'));
                }

                thisElement.addClass('active');
            }

            iElement.bind('click', function () {
                //is toggled open
                if (iElement.hasClass('md-warn')) {
                    disableChildren(collapseScope, iElement.parent().parent());
                    replaceClass('fa-minus', 'fa-plus', iElement.find('i'));
                    replaceClass('md-warn', 'md-primary', iElement);
                }
                //is toggled closed
                else if (iElement.hasClass('md-primary')) {
                    replaceClass('fa-plus', 'fa-minus', iElement.find('i'));
                    replaceClass('md-primary', 'md-warn', iElement);
                }
                //hasn't been toggled
                else {
                    disableChildren(collapseScope, iElement.parent().parent());
                    replaceClass('fa-plus', 'fa-minus', iElement.find('i'));
                    iElement.addClass('md-warn');
                }
            });
        }
    }

    // okToggleColor.$inject = [];

    app.directive('okToggleColor', okToggleColor);

})();
<commit_msg>fix to the toggle-color directive<commit_after>(function () {
    'use strict';

    var app = angular.module('SharedDirectives');

    /**
     * @ngdoc directive
     * @name SharedDirectives.directive:ok-toggle-color
     * @restrict A
     * @requires SharedDirectives.directive:ok-collapse
     *
     * @description
     * `ok-toggle-color`
     *
     *  Added to an element that has an ok-collapse attribute attached to it. Requires the same attributes as ok-collapse.
     *  Toggles primary to warning color and minus to plus classes (font awesome).
     * @usage
     * <button ok-collapse ok-toggle-color linked-to="uniqueId" all-linked-nodes="['uniqueIdOne', 'uniqueIdTwo']">
     *
     *</button>
     *

     *

     */

    function okToggleColor() {
        return {
            restrict: 'A',
            link: linkFunc
        };

        function linkFunc(scope, iElement, iAttrs) {
            var collapseScope = iElement.isolateScope();

            function replaceClass(oldClass, newClass, element) {
                element.addClass(newClass);
                element.removeClass(oldClass);
            }

            function resetAllButtons(iconElements, buttonElement) {
                var i;
                for (i = 0; i < iconElements.length; i++) {
                    var currentElement = angular.element(iconElements[i]);
                    if (currentElement.hasClass('fa') && currentElement.hasClass('fa-plus') ||
                        currentElement.hasClass('fa-minus')) {
                        replaceClass('fa-minus', 'fa-plus', currentElement);
                        currentElement.parent().removeClass('md-warn');
                        currentElement.parent().removeClass('md-primary');
                    }
                }
            }

            function disableChildren(collapseScope, thisElement) {
                var allNodes = collapseScope.allLinkedNodes,
                    i = allNodes.indexOf(collapseScope.linkedTo);
                for (i; i < allNodes.length; i++) {
                    var node = angular.element(document.getElementById(allNodes[i]));

                    node.children().removeClass('active');

                    resetAllButtons(node.find('a').find('i'), node.find('a'));
                }

                thisElement.addClass('active');
            }

            iElement.bind('click', function () {
                //is toggled open
                if (iElement.hasClass('md-warn')) {
                    disableChildren(collapseScope, iElement.parent().parent());
                    replaceClass('fa-minus', 'fa-plus', iElement.find('i'));
                    replaceClass('md-warn', 'md-primary', iElement);
                }
                //is toggled closed
                else if (iElement.hasClass('md-primary')) {
                    replaceClass('fa-plus', 'fa-minus', iElement.find('i'));
                    replaceClass('md-primary', 'md-warn', iElement);
                }
                //hasn't been toggled
                else {
                    disableChildren(collapseScope, iElement.parent().parent());
                    replaceClass('fa-plus', 'fa-minus', iElement.find('i'));
                    iElement.addClass('md-warn');
                }
            });
        }
    }

    // okToggleColor.$inject = [];

    app.directive('okToggleColor', okToggleColor);

})();
<|endoftext|>


<commit_before>// Much of this borrowed from https://github.com/sindresorhus/package-json/blob/master/index.js

const got = require('got');
const url = require('url');
const ini = require('ini');
const delay = require('delay');
const getRegistryUrl = require('registry-auth-token/registry-url');
const registryAuthToken = require('registry-auth-token');
const parse = require('github-url-from-git');
const { isBase64 } = require('validator');

module.exports = {
  maskToken,
  setNpmrc,
  getDependency,
  resetMemCache,
  resetCache,
};

let map = new Map();

let memcache = {};

let npmrc = null;

function resetMemCache() {
  logger.debug('resetMemCache()');
  memcache = {};
}

function resetCache() {
  map = new Map();
  resetMemCache();
}

// istanbul ignore next
function maskToken(token) {
  // istanbul ignore if
  if (!token) {
    return token;
  }
  return `${token.substring(0, 2)}${new Array(token.length - 3).join(
    '*'
  )}${token.slice(-2)}`;
}

function setNpmrc(input, exposeEnv = false) {
  if (input) {
    logger.debug('Setting npmrc');
    npmrc = ini.parse(input);
    // massage _auth to _authToken
    for (const [key, val] of Object.entries(npmrc)) {
      if (key.endsWith('_auth')) {
        logger.debug('Massaging _auth to _authToken');
        npmrc[key + 'Token'] = val;
        npmrc.massagedAuth = true;
        delete npmrc[key];
      }
    }
    if (!exposeEnv) {
      return;
    }
    for (const key in npmrc) {
      if (Object.prototype.hasOwnProperty.call(npmrc, key)) {
        npmrc[key] = envReplace(npmrc[key]);
      }
    }
  } else if (npmrc) {
    logger.debug('Resetting npmrc');
    npmrc = null;
  }
}

function envReplace(value, env = process.env) {
  // istanbul ignore if
  if (typeof value !== 'string' || !value) {
    return value;
  }

  const ENV_EXPR = /(\\*)\$\{([^}]+)\}/g;

  return value.replace(ENV_EXPR, (match, esc, envVarName) => {
    if (env[envVarName] === undefined) {
      logger.warn('Failed to replace env in config: ' + match);
      throw new Error('env-replace');
    }
    return env[envVarName];
  });
}

async function getDependency(name, retries = 5) {
  logger.trace(`getDependency(${name})`);
  if (memcache[name]) {
    logger.trace('Returning cached result');
    return memcache[name];
  }
  const scope = name.split('/')[0];
  let regUrl;
  try {
    regUrl = getRegistryUrl(scope, npmrc);
  } catch (err) {
    regUrl = 'https://registry.npmjs.org';
  }
  const pkgUrl = url.resolve(
    regUrl,
    encodeURIComponent(name).replace(/^%40/, '@')
  );
  const authInfo = registryAuthToken(regUrl, { npmrc });
  const headers = {};

  if (authInfo && authInfo.type && authInfo.token) {
    // istanbul ignore if
    if (npmrc && npmrc.massagedAuth && isBase64(authInfo.token)) {
      logger.debug('Massaging authorization type to Basic');
      authInfo.type = 'Basic';
    }
    headers.authorization = `${authInfo.type} ${authInfo.token}`;
  } else if (process.env.NPM_TOKEN && process.env.NPM_TOKEN !== 'undefined') {
    headers.authorization = `Bearer ${process.env.NPM_TOKEN}`;
  }

  // Retrieve from API if not cached
  try {
    const res = (await got(pkgUrl, {
      cache: process.env.RENOVATE_SKIP_CACHE ? undefined : map,
      json: true,
      retries: 5,
      headers,
    })).body;
    if (!res.versions || !Object.keys(res.versions).length) {
      // Registry returned a 200 OK but with no versions
      if (retries <= 0) {
        logger.info({ name }, 'No versions returned');
        return null;
      }
      logger.info('No versions returned, retrying');
      await delay(5000 / retries);
      return getDependency(name, 0);
    }

    const latestVersion = res.versions[res['dist-tags'].latest];
    res.repository = res.repository || latestVersion.repository;
    res.homepage = res.homepage || latestVersion.homepage;

    // Determine repository URL
    let repositoryUrl;

    if (res.repository) {
      repositoryUrl = parse(res.repository.url);
    }
    if (!repositoryUrl) {
      repositoryUrl = res.homepage;
    }
    // Simplify response before caching and returning
    const dep = {
      name: res.name,
      homepage: res.homepage,
      repositoryUrl,
      versions: res.versions,
      'dist-tags': res['dist-tags'],
      'renovate-config': latestVersion['renovate-config'],
    };
    Object.keys(dep.versions).forEach(version => {
      if (dep.versions[version].deprecated) {
        delete dep.versions[version];
      } else {
        // We don't use any of the version payload currently
        dep.versions[version] = {
          // fall back to arbitrary time for old npm servers
          time: res.time ? res.time[version] : '2017-01-01T12:00:00.000Z',
        };
      }
    });
    logger.trace({ dep }, 'dep');
    memcache[name] = dep;
    return dep;
  } catch (err) {
    if (err.statusCode === 401 || err.statusCode === 403) {
      logger.info(
        {
          pkgUrl,
          authInfoType: authInfo ? authInfo.type : undefined,
          authInfoToken: authInfo ? maskToken(authInfo.token) : undefined,
          err,
          statusCode: err.statusCode,
          name,
        },
        `Dependency lookup failure: unauthorized`
      );
      return null;
    }
    if (err.statusCode === 404 || err.code === 'ENOTFOUND') {
      logger.info({ name }, `Dependency lookup failure: not found`);
      logger.debug({
        err,
        token: authInfo ? maskToken(authInfo.token) : 'none',
      });
      return null;
    }
    if (err.name === 'ParseError') {
      // Registry returned a 200 OK but got failed to parse it
      if (retries <= 0) {
        logger.warn({ err }, 'npm registry failure: ParseError');
        throw new Error('registry-failure');
      }
      logger.info({ err }, 'npm registry failure: ParseError, retrying');
      await delay(5000 / retries);
      return getDependency(name, retries - 1);
    }
    if (err.statusCode === 429) {
      // This is bad if it ever happens, so we should error
      logger.error({ err }, 'npm registry failure: too many requests');
      throw new Error('registry-failure');
    }
    if (err.statusCode === 408) {
      if (retries <= 0) {
        logger.warn({ err }, 'npm registry failure: timeout, retries=0');
        throw new Error('registry-failure');
      }
      logger.info({ err }, 'npm registry failure: timeout, retrying');
      await delay(5000 / retries);
      return getDependency(name, retries - 1);
    }
    if (err.statusCode >= 500 && err.statusCode < 600) {
      if (retries <= 0) {
        logger.warn({ err }, 'npm registry failure: internal error, retries=0');
        throw new Error('registry-failure');
      }
      logger.info({ err }, 'npm registry failure: internal error, retrying');
      await delay(5000 / retries);
      return getDependency(name, retries - 1);
    }
    logger.warn({ err, name }, 'npm registry failure: Unknown error');
    throw new Error('registry-failure');
  }
}
<commit_msg>fix(npm): deprecate only if deprecated === ‘this’<commit_after>// Much of this borrowed from https://github.com/sindresorhus/package-json/blob/master/index.js

const got = require('got');
const url = require('url');
const ini = require('ini');
const delay = require('delay');
const getRegistryUrl = require('registry-auth-token/registry-url');
const registryAuthToken = require('registry-auth-token');
const parse = require('github-url-from-git');
const { isBase64 } = require('validator');

module.exports = {
  maskToken,
  setNpmrc,
  getDependency,
  resetMemCache,
  resetCache,
};

let map = new Map();

let memcache = {};

let npmrc = null;

function resetMemCache() {
  logger.debug('resetMemCache()');
  memcache = {};
}

function resetCache() {
  map = new Map();
  resetMemCache();
}

// istanbul ignore next
function maskToken(token) {
  // istanbul ignore if
  if (!token) {
    return token;
  }
  return `${token.substring(0, 2)}${new Array(token.length - 3).join(
    '*'
  )}${token.slice(-2)}`;
}

function setNpmrc(input, exposeEnv = false) {
  if (input) {
    logger.debug('Setting npmrc');
    npmrc = ini.parse(input);
    // massage _auth to _authToken
    for (const [key, val] of Object.entries(npmrc)) {
      if (key.endsWith('_auth')) {
        logger.debug('Massaging _auth to _authToken');
        npmrc[key + 'Token'] = val;
        npmrc.massagedAuth = true;
        delete npmrc[key];
      }
    }
    if (!exposeEnv) {
      return;
    }
    for (const key in npmrc) {
      if (Object.prototype.hasOwnProperty.call(npmrc, key)) {
        npmrc[key] = envReplace(npmrc[key]);
      }
    }
  } else if (npmrc) {
    logger.debug('Resetting npmrc');
    npmrc = null;
  }
}

function envReplace(value, env = process.env) {
  // istanbul ignore if
  if (typeof value !== 'string' || !value) {
    return value;
  }

  const ENV_EXPR = /(\\*)\$\{([^}]+)\}/g;

  return value.replace(ENV_EXPR, (match, esc, envVarName) => {
    if (env[envVarName] === undefined) {
      logger.warn('Failed to replace env in config: ' + match);
      throw new Error('env-replace');
    }
    return env[envVarName];
  });
}

async function getDependency(name, retries = 5) {
  logger.trace(`getDependency(${name})`);
  if (memcache[name]) {
    logger.trace('Returning cached result');
    return memcache[name];
  }
  const scope = name.split('/')[0];
  let regUrl;
  try {
    regUrl = getRegistryUrl(scope, npmrc);
  } catch (err) {
    regUrl = 'https://registry.npmjs.org';
  }
  const pkgUrl = url.resolve(
    regUrl,
    encodeURIComponent(name).replace(/^%40/, '@')
  );
  const authInfo = registryAuthToken(regUrl, { npmrc });
  const headers = {};

  if (authInfo && authInfo.type && authInfo.token) {
    // istanbul ignore if
    if (npmrc && npmrc.massagedAuth && isBase64(authInfo.token)) {
      logger.debug('Massaging authorization type to Basic');
      authInfo.type = 'Basic';
    }
    headers.authorization = `${authInfo.type} ${authInfo.token}`;
  } else if (process.env.NPM_TOKEN && process.env.NPM_TOKEN !== 'undefined') {
    headers.authorization = `Bearer ${process.env.NPM_TOKEN}`;
  }

  // Retrieve from API if not cached
  try {
    const res = (await got(pkgUrl, {
      cache: process.env.RENOVATE_SKIP_CACHE ? undefined : map,
      json: true,
      retries: 5,
      headers,
    })).body;
    if (!res.versions || !Object.keys(res.versions).length) {
      // Registry returned a 200 OK but with no versions
      if (retries <= 0) {
        logger.info({ name }, 'No versions returned');
        return null;
      }
      logger.info('No versions returned, retrying');
      await delay(5000 / retries);
      return getDependency(name, 0);
    }

    const latestVersion = res.versions[res['dist-tags'].latest];
    res.repository = res.repository || latestVersion.repository;
    res.homepage = res.homepage || latestVersion.homepage;

    // Determine repository URL
    let repositoryUrl;

    if (res.repository) {
      repositoryUrl = parse(res.repository.url);
    }
    if (!repositoryUrl) {
      repositoryUrl = res.homepage;
    }
    // Simplify response before caching and returning
    const dep = {
      name: res.name,
      homepage: res.homepage,
      repositoryUrl,
      versions: res.versions,
      'dist-tags': res['dist-tags'],
      'renovate-config': latestVersion['renovate-config'],
    };
    Object.keys(dep.versions).forEach(version => {
      if (dep.versions[version].deprecated === 'this') {
        delete dep.versions[version];
      } else {
        // We don't use any of the version payload currently
        dep.versions[version] = {
          // fall back to arbitrary time for old npm servers
          time: res.time ? res.time[version] : '2017-01-01T12:00:00.000Z',
        };
      }
    });
    logger.trace({ dep }, 'dep');
    memcache[name] = dep;
    return dep;
  } catch (err) {
    if (err.statusCode === 401 || err.statusCode === 403) {
      logger.info(
        {
          pkgUrl,
          authInfoType: authInfo ? authInfo.type : undefined,
          authInfoToken: authInfo ? maskToken(authInfo.token) : undefined,
          err,
          statusCode: err.statusCode,
          name,
        },
        `Dependency lookup failure: unauthorized`
      );
      return null;
    }
    if (err.statusCode === 404 || err.code === 'ENOTFOUND') {
      logger.info({ name }, `Dependency lookup failure: not found`);
      logger.debug({
        err,
        token: authInfo ? maskToken(authInfo.token) : 'none',
      });
      return null;
    }
    if (err.name === 'ParseError') {
      // Registry returned a 200 OK but got failed to parse it
      if (retries <= 0) {
        logger.warn({ err }, 'npm registry failure: ParseError');
        throw new Error('registry-failure');
      }
      logger.info({ err }, 'npm registry failure: ParseError, retrying');
      await delay(5000 / retries);
      return getDependency(name, retries - 1);
    }
    if (err.statusCode === 429) {
      // This is bad if it ever happens, so we should error
      logger.error({ err }, 'npm registry failure: too many requests');
      throw new Error('registry-failure');
    }
    if (err.statusCode === 408) {
      if (retries <= 0) {
        logger.warn({ err }, 'npm registry failure: timeout, retries=0');
        throw new Error('registry-failure');
      }
      logger.info({ err }, 'npm registry failure: timeout, retrying');
      await delay(5000 / retries);
      return getDependency(name, retries - 1);
    }
    if (err.statusCode >= 500 && err.statusCode < 600) {
      if (retries <= 0) {
        logger.warn({ err }, 'npm registry failure: internal error, retries=0');
        throw new Error('registry-failure');
      }
      logger.info({ err }, 'npm registry failure: internal error, retrying');
      await delay(5000 / retries);
      return getDependency(name, retries - 1);
    }
    logger.warn({ err, name }, 'npm registry failure: Unknown error');
    throw new Error('registry-failure');
  }
}
<|endoftext|>